From 100578a3ba8a3105c8d8d91933a48751b6a23329 Mon Sep 17 00:00:00 2001 From: Dan Date: Mon, 1 Jan 2024 01:53:28 -0800 Subject: [PATCH] fixes after merging master --- VortexEngine/src/Log/Log.cpp | 37 ++++++++ VortexEngine/src/Serial/Serial.cpp | 4 + VortexEngine/src/Wireless/IRSender.cpp | 11 ++- VortexEngine/src/Wireless/IRSender.h | 5 ++ VortexEngine/src/Wireless/VLReceiver.cpp | 103 +++++++++++++++++++++++ 5 files changed, 159 insertions(+), 1 deletion(-) diff --git a/VortexEngine/src/Log/Log.cpp b/VortexEngine/src/Log/Log.cpp index 6d4b24ce95..c79ff42b06 100644 --- a/VortexEngine/src/Log/Log.cpp +++ b/VortexEngine/src/Log/Log.cpp @@ -18,9 +18,20 @@ #if LOGGING_LEVEL > 0 void InfoMsg(const char *msg, ...) { +#ifdef VORTEX_EMBEDDED + if (!SerialComs::isConnected()) { + return; + } +#endif va_list list; va_start(list, msg); +#ifdef VORTEX_EMBEDDED + char buf[2048] = {0}; + vsnprintf(buf, sizeof(buf), msg, list); + Serial.println(buf); +#else Vortex::printlog(NULL, NULL, 0, msg, list); +#endif va_end(list); } #endif @@ -28,9 +39,22 @@ void InfoMsg(const char *msg, ...) #if LOGGING_LEVEL > 1 void ErrorMsg(const char *func, const char *msg, ...) { +#ifdef VORTEX_EMBEDDED + if (!SerialComs::isConnected()) { + return; + } +#endif va_list list; va_start(list, msg); +#ifdef VORTEX_EMBEDDED + char fmt[2048] = {0}; + snprintf(fmt, sizeof(fmt), "%s(): %s", func, msg); + char buf[2048] = {0}; + vsnprintf(buf, sizeof(buf), fmt, list); + Serial.println(buf); +#else Vortex::printlog(NULL, func, 0, msg, list); +#endif va_end(list); } #endif @@ -38,6 +62,11 @@ void ErrorMsg(const char *func, const char *msg, ...) #if LOGGING_LEVEL > 2 void DebugMsg(const char *file, const char *func, int line, const char *msg, ...) { +#ifdef VORTEX_EMBEDDED + if (!SerialComs::isConnected()) { + return; + } +#endif va_list list; va_start(list, msg); const char *ptr = file + strlen(file); @@ -50,7 +79,15 @@ void DebugMsg(const char *file, const char *func, int line, const char *msg, ... } ptr--; } +#ifdef VORTEX_EMBEDDED + char fmt[2048] = {0}; + snprintf(fmt, sizeof(fmt), "%s:%d %s(): %s", file, line, func, msg); + char buf[2048] = {0}; + vsnprintf(buf, sizeof(buf), fmt, list); + Serial.println(buf); +#else Vortex::printlog(file, func, line, msg, list); +#endif va_end(list); } #endif diff --git a/VortexEngine/src/Serial/Serial.cpp b/VortexEngine/src/Serial/Serial.cpp index 2d3c4bd343..f858954b39 100644 --- a/VortexEngine/src/Serial/Serial.cpp +++ b/VortexEngine/src/Serial/Serial.cpp @@ -12,6 +12,10 @@ #include #endif +#ifdef VORTEX_EMBEDDED +#include +#endif + bool SerialComs::m_serialConnected = false; uint32_t SerialComs::m_lastCheck = 0; diff --git a/VortexEngine/src/Wireless/IRSender.cpp b/VortexEngine/src/Wireless/IRSender.cpp index 28d2a6c4da..dc31c4aa9d 100644 --- a/VortexEngine/src/Wireless/IRSender.cpp +++ b/VortexEngine/src/Wireless/IRSender.cpp @@ -35,8 +35,15 @@ uint32_t IRSender::m_blockSize = 0; // write total uint32_t IRSender::m_writeCounter = 0; +#if defined(VORTEX_EMBEDDED) +// Timer used for PWM, is initialized in initpwm() +Tcc *IR_TCCx; +#endif + bool IRSender::init() { + // initialize the IR device + initPWM(); return true; } @@ -116,6 +123,8 @@ void IRSender::beginSend() m_isSending = true; DEBUG_LOGF("[%zu] Beginning send size %u (blocks: %u remainder: %u blocksize: %u)", Time::microseconds(), m_size, m_numBlocks, m_remainder, m_blockSize); + // init sender before writing, is this necessary here? I think so + initPWM(); // wakeup the other receiver with a very quick mark/space sendMark(50); sendSpace(100); @@ -186,7 +195,7 @@ void IRSender::initPWM() // F & E peripherals specify the timers: TCC0, TCC1 and TCC2 PORT->Group[port].PMUX[pin >> 1].reg |= IR_PER_EorF; - // pinPeripheral (IR_SEND_PWM_PIN,PIO_TIMER_ALT); +// pinPeripheral (IR_SEND_PWM_PIN,PIO_TIMER_ALT); // Feed GCLK0 to TCC0 and TCC1 REG_GCLK_CLKCTRL = GCLK_CLKCTRL_CLKEN | // Enable GCLK0 to TCC0 and TCC1 GCLK_CLKCTRL_GEN_GCLK0 | // Select GCLK0 diff --git a/VortexEngine/src/Wireless/IRSender.h b/VortexEngine/src/Wireless/IRSender.h index 8f65fa7048..d8e9df30eb 100644 --- a/VortexEngine/src/Wireless/IRSender.h +++ b/VortexEngine/src/Wireless/IRSender.h @@ -34,6 +34,11 @@ class IRSender // send a mark/space by turning PWM on/off static void sendMark(uint16_t time); static void sendSpace(uint16_t time); + // Pulse-Width Modulator (IR Transmitter) + static void initPWM(); + // turn the IR transmitter on/off in realtime + static void startPWM(); + static void stopPWM(); // the serial buffer for the data static ByteStream m_serialBuf; diff --git a/VortexEngine/src/Wireless/VLReceiver.cpp b/VortexEngine/src/Wireless/VLReceiver.cpp index d418986fb0..f4a7815213 100644 --- a/VortexEngine/src/Wireless/VLReceiver.cpp +++ b/VortexEngine/src/Wireless/VLReceiver.cpp @@ -7,6 +7,11 @@ #include "../Leds/Leds.h" #include "../Log/Log.h" +#ifdef VORTEX_EMBEDDED +#include +#include +#endif + #if VL_ENABLE_RECEIVER == 1 BitStream VLReceiver::m_vlData; @@ -15,8 +20,51 @@ uint32_t VLReceiver::m_prevTime = 0; uint8_t VLReceiver::m_pinState = 0; uint32_t VLReceiver::m_previousBytes = 0; +#ifdef VORTEX_EMBEDDED +#define MIN_THRESHOLD 200 +#define BASE_OFFSET 100 +#define THRESHOLD_BEGIN (MIN_THRESHOLD + BASE_OFFSET) +// the sample count exponent, so 5 means 2^5 = 32 samples +// 0 NONE No accumulation > doesn't work +// 1 ACC2 2 results accumulated > doesn't work +// 2 ACC4 4 results accumulated > works okay +// 3 ACC8 8 results accumulated > works decent +// 4 ACC16 16 results accumulated > works very well +// 5 ACC32 32 results accumulated > works best +// 6 ACC64 64 results accumulated > doesn't work +#define SAMPLE_COUNT 5 +// the threshold needs to start high then it will be automatically pulled down +uint16_t threshold = THRESHOLD_BEGIN; +ISR(ADC0_WCOMP_vect) +{ + // this will store the last known state + static bool wasAboveThreshold = false; + // grab the current analog value but divide it by 8 (the number of samples) + uint16_t val = (ADC0.RES >> SAMPLE_COUNT); + // calculate a threshold by using the baseline minimum value that is above 0 + // with a static offset, this ensures whatever the baseline light level and/or + // hardware sensitivity is it will always pick a threshold just above the 'off' + if (val > MIN_THRESHOLD && val < (threshold + BASE_OFFSET)) { + threshold = val + BASE_OFFSET; + } + // compare the current analog value to the light threshold + bool isAboveThreshold = (val > threshold); + if (wasAboveThreshold != isAboveThreshold) { + VLReceiver::recvPCIHandler(); + wasAboveThreshold = isAboveThreshold; + } + // Clear the Window Comparator interrupt flag + ADC0.INTFLAGS = ADC_WCMP_bm; +} +#endif + bool VLReceiver::init() { +#ifdef VORTEX_EMBEDDED + // Disable digital input buffer on the pin to save power + PORTB.PIN1CTRL &= ~PORT_ISC_gm; + PORTB.PIN1CTRL |= PORT_ISC_INPUT_DISABLE_gc; +#endif return m_vlData.init(VL_RECV_BUF_SIZE); } @@ -82,12 +130,63 @@ bool VLReceiver::receiveMode(Mode *pMode) bool VLReceiver::beginReceiving() { +#ifdef VORTEX_EMBEDDED + // Set up the ADC + // sample campacitance, VDD reference, prescaler division + // Options are: + // 0x0 DIV2 CLK_PER divided by 2 > works + // 0x1 DIV4 CLK_PER divided by 4 > works + // 0x2 DIV8 CLK_PER divided by 8 > works + // 0x3 DIV16 CLK_PER divided by 16 > works + // 0x4 DIV32 CLK_PER divided by 32 > doesn't work + // 0x5 DIV64 CLK_PER divided by 64 > doesn't work + // 0x6 DIV128 CLK_PER divided by 128 > doesn't work + // 0x7 DIV256 CLK_PER divided by 256 > doesn't work +#if (F_CPU == 20000000) + ADC0.CTRLC = ADC_SAMPCAP_bm | ADC_REFSEL_VDDREF_gc | ADC_PRESC_DIV2_gc; +#else + ADC0.CTRLC = ADC_SAMPCAP_bm | ADC_REFSEL_VDDREF_gc | ADC_PRESC_DIV2_gc; +#endif + // no sampling delay and no delay variation + ADC0.CTRLD = 0; + // sample length + // 0 = doesn't work + // 1+ = works + ADC0.SAMPCTRL = 1; + // Select the analog pin input PB1 (AIN10) + ADC0.MUXPOS = ADC_MUXPOS_AIN10_gc; + // Initialize the Window Comparator Mode in above + ADC0.CTRLE = ADC_WINCM_ABOVE_gc; + // Set the threshold value very low + ADC0.WINHT = 0x1; + ADC0.WINLT = 0; + // set sampling amount + // 0x0 NONE No accumulation > doesn't work + // 0x1 ACC2 2 results accumulated > doesn't work + // 0x2 ACC4 4 results accumulated > works okay + // 0x3 ACC8 8 results accumulated > works decent + // 0x4 ACC16 16 results accumulated > works very well + // 0x5 ACC32 32 results accumulated > works best + // 0x6 ACC64 64 results accumulated > doesn't work + ADC0.CTRLB = SAMPLE_COUNT; + // Enable Window Comparator interrupt + ADC0.INTCTRL = ADC_WCMP_bm; + // Enable the ADC and start continuous conversions + ADC0.CTRLA = ADC_ENABLE_bm | ADC_FREERUN_bm; + // start the first conversion + ADC0.COMMAND = ADC_STCONV_bm; +#endif resetVLState(); return true; } bool VLReceiver::endReceiving() { +#ifdef VORTEX_EMBEDDED + // Stop conversions and disable the ADC + ADC0.CTRLA &= ~(ADC_ENABLE_bm | ADC_FREERUN_bm); + ADC0.INTCTRL = 0; +#endif resetVLState(); return true; } @@ -196,6 +295,10 @@ void VLReceiver::resetVLState() m_recvState = WAITING_HEADER_MARK; // zero out the receive buffer and reset bit receiver position m_vlData.reset(); +#ifdef VORTEX_EMBEDDED + // reset the threshold to a high value so that it can be pulled down again + threshold = THRESHOLD_BEGIN; +#endif DEBUG_LOG("VL State Reset"); }