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.
 
 
OpenAudio_ArduinoLibrary/UART_F32.cpp

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);
}