/* * UART_F32.cpp * * 10 JUne 2022 - Separated from FM Discriminator * Bob Larkin, in support of the library: * Chip Audette, OpenAudio, Apr 2017 * ------------------- * * Copyright (c) 2022 Bob Larkin * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. * * See UART_F32.h for usage details */ #include "UART_F32.h" void UART_F32::update(void) { audio_block_f32_t *blockIn; int i; bool downTransition; float32_t dataIn; // For measuring timing // uint32_t t1 = micros(); // Get input to UART block blockIn = AudioStream_F32::receiveWritable_f32(0); if (!blockIn) { return; } /* Simple UART - Start idle state. Wait for Start Bit, wait 0.5 bit periods * and read Start bit. Read next data bits every cTauI samples. After last data bit * is read, go back to idle state. This gives a half bit period to allow for fast * sending clocks. */ for (i=0; idata[i] + inputOffset; // Programmable offset, if needed downTransition = (dataIn<=0.0f && yLast>0.0f); yLast = dataIn; if(serialState==SERIAL_DATA_FINISHED) // Have data bits, waiting to read stop bit { //Serial.print(sClock); Serial.print("sc next"); Serial.println(cSampleNext); if(sClock>=cSampleNext) { // Serial.print(" @"); Serial.print(serialState); Serial.println("@"); if(dataIn > 0.0f) // Valid Stop Bit { // Serial.println("P"); // Stop bit is correct writeUartData(dataWord, saveStatus, elapsedTime); saveStatus &= ERR_OVERRUN; // Error indicator has been sent, don't clear overrun } else // Wrong logic level { // Many low S/N frame errors are just bit-read errors and not timing errors. // No way to tell which, and best to just accept data. // Serial.println("F"); // Data has been read with Framing error saveStatus |= ERR_FRAME; writeUartData(dataWord, saveStatus, elapsedTime); saveStatus &= ERR_OVERRUN; // Error indicator has been sent, don't clear overrun } serialState = SERIAL_IDLE; // Return to waiting for start bit bitCount = 0; bitMask = 1UL; dataWord = 0UL; elapsedTime = 0; } } else if(serialState==SERIAL_DATA) { if(sClock>=cSampleNext) { if(bitCount==0) // Going to read start bit { if(dataIn<=0.0f) // Valid start bit { //Serial.print("T"); // Logic is low at data read time for valid start bit bitCount = 1; bitMask = 1UL; dataWord = 0UL; cSampleNext += cTauI; } else // Not low, must be noise, cancel out { serialState = SERIAL_IDLE; bitCount = 0; cSampleNext = 0; } } else // bitCount>0 so reading data bits { if(dataIn >= 0.0f) { // Serial.print("1"); // Data bit is a 1 dataWord |= bitMask; } else { // Serial.print("0"); // Data bit // Data bit is already zero } bitMask = (bitMask << 1); cSampleNext += cTauI; bitCount++; if(bitCount>=nTotal) // Last data bit { serialState = SERIAL_DATA_FINISHED; // Look for valid stop bit bitCount = 0; } } } } else if(serialState==SERIAL_IDLE) // Waiting for a Start Bit { if(downTransition) // Down going, potential start bit { serialState = SERIAL_DATA; timeStartBit = sClock; cSampleNext = sClock + cTauHalfI; // This will sample start bit bitCount = 0; } } // UART done, now gather data for checking clock accuracy // Use timeStartBit and time of last down transitions. // Up transitions may have a bias and are not used. if(downTransition) { elapsedTime = (int32_t)(sClock - timeStartBit); } } AudioStream_F32::release(blockIn); // Serial.print("At end of UART "); Serial.println (micros() - t1); }