Skip to content

Commit

Permalink
fixes for IR send and receive
Browse files Browse the repository at this point in the history
  • Loading branch information
Unreal-Dan committed Sep 16, 2024
1 parent 79a1af5 commit 2d13e1a
Show file tree
Hide file tree
Showing 5 changed files with 234 additions and 24 deletions.
168 changes: 153 additions & 15 deletions VortexEngine/src/Menus/MenuList/ModeSharing.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
#include "../../Time/Timings.h"
#include "../../Wireless/VLReceiver.h"
#include "../../Wireless/VLSender.h"
#include "../../Wireless/VLSender.h"
#include "../../Wireless/IRReceiver.h"
#include "../../Wireless/IRSender.h"
#include "../../Buttons/Button.h"
#include "../../Modes/Modes.h"
#include "../../Modes/Mode.h"
Expand All @@ -15,8 +16,10 @@

ModeSharing::ModeSharing(const RGBColor &col, bool advanced) :
Menu(col, advanced),
m_sharingMode(ModeShareState::SHARE_RECEIVE),
m_timeOutStartTime(0)
m_sharingMode(ModeShareState::SHARE_RECEIVE_VL),
m_timeOutStartTime(0),
m_lastSendTime(0),
m_shouldEndSend(false)
{
}

Expand Down Expand Up @@ -46,17 +49,29 @@ Menu::MenuAction ModeSharing::run()
return result;
}
switch (m_sharingMode) {
case ModeShareState::SHARE_RECEIVE_VL:
// render the 'receive mode' lights
showReceiveModeVL();
// load any modes that are received
receiveModeVL();
break;
case ModeShareState::SHARE_SEND_VL:
// render the 'send mode' lights
showSendModeVL();
// continue sending any data as long as there is more to send
continueSendingVL();
break;
case ModeShareState::SHARE_RECEIVE:
case ModeShareState::SHARE_RECEIVE_IR:
// render the 'receive mode' lights
showReceiveMode();
showReceiveModeIR();
// load any modes that are received
receiveModeVL();
receiveModeIR();
break;
case ModeShareState::SHARE_SEND_IR:
// render the 'send mode' lights
showSendModeIR();
// continue sending any data as long as there is more to send
continueSendingIR();
break;
}
return MENU_CONTINUE;
Expand All @@ -66,11 +81,22 @@ Menu::MenuAction ModeSharing::run()
void ModeSharing::onShortClickM()
{
switch (m_sharingMode) {
case ModeShareState::SHARE_RECEIVE:
case ModeShareState::SHARE_RECEIVE_VL:
// click while on receive -> end receive, start sending
VLReceiver::endReceiving();
beginSendingVL();
DEBUG_LOG("Switched to send mode");
DEBUG_LOG("Switched to send VL");
break;
case ModeShareState::SHARE_RECEIVE_IR:
if (!IRSender::isSending()) {
beginSendingIR();
DEBUG_LOG("Switched to send IR");
} else {
m_shouldEndSend = true;
}
break;
case ModeShareState::SHARE_SEND_IR:
m_shouldEndSend = true;
break;
default:
break;
Expand All @@ -79,28 +105,116 @@ void ModeSharing::onShortClickM()
}

// handlers for clicks
void ModeSharing::onShortClickL()
{
switchVLIR();
}

void ModeSharing::onShortClickR()
{
switchVLIR();
}

void ModeSharing::switchVLIR()
{
switch (m_sharingMode) {
case ModeShareState::SHARE_RECEIVE:
// click while on receive -> end receive, start sending
case ModeShareState::SHARE_RECEIVE_VL:
VLReceiver::endReceiving();
beginSendingVL();
DEBUG_LOG("Switched to send mode");
beginReceivingIR();
break;
case ModeShareState::SHARE_RECEIVE_IR:
IRReceiver::endReceiving();
beginReceivingVL();
break;
default:
break;
}
Leds::clearAll();
}


void ModeSharing::onLongClickM()
{
Modes::updateCurMode(&m_previewMode);
leaveMenu(true);
}

void ModeSharing::beginSendingIR()
{
// if the sender is sending then cannot start again
if (IRSender::isSending()) {
ERROR_LOG("Cannot begin sending, sender is busy");
return;
}
m_sharingMode = ModeShareState::SHARE_SEND_IR;
Leds::clearAll();
Leds::update();
// initialize it with the current mode data
IRSender::loadMode(Modes::curMode());
// send the first chunk of data, leave if we're done
if (!IRSender::send()) {
// just set the last time and wait
m_lastSendTime = Time::getCurtime();
}
DEBUG_LOG("Switched to sending IR");
}

void ModeSharing::continueSendingIR()
{
// if the sender isn't sending then nothing to do
if (!IRSender::isSending()) {
if (m_lastSendTime && m_lastSendTime < (Time::getCurtime() + MS_TO_TICKS(350))) {
if (m_shouldEndSend) {
beginReceivingIR();
m_shouldEndSend = false;
} else {
beginSendingIR();
}
}
return;
}
if (!IRSender::send()) {
// just set the last time and wait
m_lastSendTime = Time::getCurtime();
}
}

void ModeSharing::beginReceivingIR()
{
m_sharingMode = ModeShareState::SHARE_RECEIVE_IR;
IRReceiver::beginReceiving();
DEBUG_LOG("Switched to receiving IR");
}

void ModeSharing::receiveModeIR()
{
// if reveiving new data set our last data time
if (IRReceiver::onNewData()) {
m_timeOutStartTime = Time::getCurtime();
// if our last data was more than time out duration reset the recveiver
} else if (m_timeOutStartTime > 0 && (m_timeOutStartTime + MAX_TIMEOUT_DURATION) < Time::getCurtime()) {
IRReceiver::resetIRState();
m_timeOutStartTime = 0;
return;
}
// check if the IRReceiver has a full packet available
if (!IRReceiver::dataReady()) {
// nothing available yet
return;
}
DEBUG_LOG("Mode ready to receive! Receiving...");
// receive the IR mode into the current mode
if (!IRReceiver::receiveMode(&m_previewMode)) {
ERROR_LOG("Failed to receive mode");
return;
}
DEBUG_LOGF("Success receiving mode: %u", m_previewMode.getPatternID());
if (!m_advanced) {
Modes::updateCurMode(&m_previewMode);
// leave menu and save settings, even if the mode was the same whatever
leaveMenu(true);
}
}

void ModeSharing::beginSendingVL()
{
// if the sender is sending then cannot start again
Expand All @@ -116,6 +230,7 @@ void ModeSharing::beginSendingVL()
// when send has completed, stores time that last action was completed to calculate interval between sends
beginReceivingVL();
}
DEBUG_LOG("Switched to sending VL");
}

void ModeSharing::continueSendingVL()
Expand All @@ -132,8 +247,9 @@ void ModeSharing::continueSendingVL()

void ModeSharing::beginReceivingVL()
{
m_sharingMode = ModeShareState::SHARE_RECEIVE;
m_sharingMode = ModeShareState::SHARE_RECEIVE_VL;
VLReceiver::beginReceiving();
DEBUG_LOG("Switched to receiving VL");
}

void ModeSharing::receiveModeVL()
Expand Down Expand Up @@ -172,7 +288,14 @@ void ModeSharing::showSendModeVL()
Leds::clearAll();
}

void ModeSharing::showReceiveMode()
void ModeSharing::showSendModeIR()
{
// show a dim color when not sending
Leds::setAll(RGB_CYAN5);
Leds::setAllEvens(RGB_CYAN0);
}

void ModeSharing::showReceiveModeVL()
{
if (VLReceiver::isReceiving()) {
// using uint32_t to avoid overflow, the result should be within 10 to 255
Expand All @@ -186,3 +309,18 @@ void ModeSharing::showReceiveMode()
}
}
}

void ModeSharing::showReceiveModeIR()
{
if (VLReceiver::isReceiving()) {
// using uint32_t to avoid overflow, the result should be within 10 to 255
Leds::clearAll();
Leds::setRange(LED_FIRST, (LedPos)(VLReceiver::percentReceived() / 10), RGBColor(0, 1, 0));
} else {
if (m_advanced) {
m_previewMode.play();
} else {
Leds::setAll(RGB_CYAN0);
}
}
}
22 changes: 19 additions & 3 deletions VortexEngine/src/Menus/MenuList/ModeSharing.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ class ModeSharing : public Menu

// handlers for clicks
void onShortClickM() override;
void onShortClickL() override;
void onShortClickR() override;
void onLongClickM() override;

Expand All @@ -23,18 +24,33 @@ class ModeSharing : public Menu
void beginReceivingVL();
void receiveModeVL();

void beginSendingIR();
void continueSendingIR();
void beginReceivingIR();
void receiveModeIR();

void showSendModeVL();
void showReceiveMode();
void showSendModeIR();
void showReceiveModeVL();
void showReceiveModeIR();

void switchVLIR();

enum class ModeShareState {
SHARE_SEND_VL, // send mode over vl
SHARE_RECEIVE, // receive mode
SHARE_RECEIVE_VL,
SHARE_SEND_VL,
SHARE_RECEIVE_IR,
SHARE_SEND_IR,
};

ModeShareState m_sharingMode;

// the start time when checking for timing out
uint32_t m_timeOutStartTime;
uint32_t m_lastSendTime;

// whether to end the next send and go back to receive
bool m_shouldEndSend;
};

#endif
25 changes: 19 additions & 6 deletions VortexEngine/src/Wireless/IRReceiver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@
#include "../Modes/Mode.h"
#include "../Log/Log.h"

#ifdef VORTEX_EMBEDDED
#include <Arduino.h>
#endif

BitStream IRReceiver::m_irData;
IRReceiver::RecvState IRReceiver::m_recvState = WAITING_HEADER_MARK;
uint32_t IRReceiver::m_prevTime = 0;
Expand All @@ -17,6 +21,9 @@ uint32_t IRReceiver::m_previousBytes = 0;

bool IRReceiver::init()
{
#ifdef VORTEX_EMBEDDED
pinMode(IR_RECEIVER_PIN, INPUT_PULLUP);
#endif
m_irData.init(IR_RECV_BUF_SIZE);
return true;
}
Expand Down Expand Up @@ -83,12 +90,18 @@ bool IRReceiver::receiveMode(Mode *pMode)

bool IRReceiver::beginReceiving()
{
#ifdef VORTEX_EMBEDDED
attachInterrupt(digitalPinToInterrupt(IR_RECEIVER_PIN), IRReceiver::recvPCIHandler, CHANGE);
#endif
resetIRState();
return true;
}

bool IRReceiver::endReceiving()
{
#ifdef VORTEX_EMBEDDED
detachInterrupt(digitalPinToInterrupt(IR_RECEIVER_PIN));
#endif
resetIRState();
return true;
}
Expand Down Expand Up @@ -138,7 +151,7 @@ void IRReceiver::recvPCIHandler()
// check previous time for validity
if (!m_prevTime || m_prevTime > now) {
m_prevTime = now;
DEBUG_LOG("Bad first time diff, resetting...");
//DEBUG_LOG("Bad first time diff, resetting...");
resetIRState();
return;
}
Expand All @@ -155,7 +168,7 @@ void IRReceiver::handleIRTiming(uint32_t diff)
{
// if the diff is too long or too short then it's not useful
if ((diff > IR_HEADER_MARK_MAX && m_recvState < READING_DATA_MARK) || diff < IR_TIMING_MIN) {
DEBUG_LOGF("bad delay: %u, resetting...", diff);
//DEBUG_LOGF("bad delay: %u, resetting...", diff);
resetIRState();
return;
}
Expand All @@ -164,15 +177,15 @@ void IRReceiver::handleIRTiming(uint32_t diff)
if (diff >= IR_HEADER_MARK_MIN && diff <= IR_HEADER_MARK_MAX) {
m_recvState = WAITING_HEADER_SPACE;
} else {
DEBUG_LOGF("Bad header mark %u, resetting...", diff);
//DEBUG_LOGF("Bad header mark %u, resetting...", diff);
resetIRState();
}
break;
case WAITING_HEADER_SPACE:
if (diff >= IR_HEADER_SPACE_MIN && diff <= IR_HEADER_SPACE_MAX) {
m_recvState = READING_DATA_MARK;
} else {
DEBUG_LOGF("Bad header space %u, resetting...", diff);
//DEBUG_LOGF("Bad header space %u, resetting...", diff);
resetIRState();
}
break;
Expand All @@ -186,7 +199,7 @@ void IRReceiver::handleIRTiming(uint32_t diff)
m_recvState = READING_DATA_MARK;
break;
default: // ??
DEBUG_LOGF("Bad receive state: %u", m_recvState);
//DEBUG_LOGF("Bad receive state: %u", m_recvState);
break;
}
}
Expand All @@ -197,7 +210,7 @@ void IRReceiver::resetIRState()
m_recvState = WAITING_HEADER_MARK;
// zero out the receive buffer and reset bit receiver position
m_irData.reset();
DEBUG_LOG("IR State Reset");
//DEBUG_LOG("IR State Reset");
}

#endif
Loading

0 comments on commit 2d13e1a

Please sign in to comment.