You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
154 lines
5.8 KiB
154 lines
5.8 KiB
/*
|
|
* 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; i<block_size; i++)
|
|
{
|
|
sClock++; // Endless 32 bit count of audio sample periods (27 hours at 44.1 kHz)
|
|
dataIn = blockIn->data[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);
|
|
}
|
|
|