-
Notifications
You must be signed in to change notification settings - Fork 32
/
UART_F32.h
216 lines (192 loc) · 7.78 KB
/
UART_F32.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
/*
* UART_F32
* 10 JUne 2022 - Separated from FM Discriminator
*
* 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.
*/
/* This object takes a single audio input representing the baseband output
* of a suitable detector such as frequency or phase. The polarity of the
* input is >0.0 for logic 1 as well as the the idle state and <0.0 for logic 0.
* The timing of the UART is specified by the
* setUART(cTauI, cTauHalfI, nBits, nParity, nStop) function. The first two
* parameters are the data bit period measured in audio sample periods,
* and half of that (roughly) that sets the number of audio sample periods between
* between the 1-to-0 transition of the start bit and the middle of the start bit.
* nBits can be between 1 and 32 (default 8). nParity can be PARITY_NONE,
* PARITY_ODD or PARITY_EVEN. nStop is currently restricted to 1, but
* this could change.
*
* Data is read using the functions
* int32_t getNDataBuffer() that returns the number of words available
* and readUartData() that returns a pointer to the oldest UART data structure:
* struct uartData {
* uint32_t data;
* uint8_t error; // Parity=01, Overrun=02, Underrun=04
* int32_t timeCrossings;}
* Up to 16 of these structures can be buffered before creating
* an ERR_OVERRUN.
*
* NOTE: Parity checking does nothing now. Needs to be added using
* the in-place function. June 2022
*
* Time: For T4.0, 7 microseconds for 128 data points.
*
*/
#ifndef _uart_f32_h
#define _uart_f32_h
#include "AudioStream_F32.h"
#include "OpenAudio_ArduinoLibrary.h"
#define SERIAL_IDLE 0
#define SERIAL_DATA 1
#define SERIAL_DATA_FINISHED 2
#define PARITY_NONE 0
#define PARITY_ODD 1
#define PARITY_EVEN 2
#define ERR_FRAME 1;
#define ERR_OVERRUN 2
#define ERR_PARITY 4
struct uartData {
uint32_t data;
uint8_t status;
int32_t timeCrossings;
};
class UART_F32 : public AudioStream_F32 {
//GUI: inputs:1, outputs:0 //this line used for automatic generation of GUI node
//GUI: shortName: uart
public:
// Default block size and sample rate:
UART_F32(void) : AudioStream_F32(1, inputQueueArray_f32) {
}
// Option of AudioSettings_F32 change to block size and/or sample rate:
UART_F32(const AudioSettings_F32 &settings) : AudioStream_F32(1, inputQueueArray_f32) {
sampleRate_Hz = settings.sample_rate_Hz;
block_size = settings.audio_block_samples;
}
void setUART(uint32_t _cTauI, uint32_t _cTauHalfI,
uint16_t _nBits, uint16_t _nParity, uint16_t _nStop) {
cTauI = _cTauI;
cTauHalfI = _cTauHalfI;
nBits = _nBits;
nStop = _nStop;
nTotal = 1 + nBits;
if(nParity > 0) nTotal++;
}
// Returns the number of unread data words
int32_t getNDataBuffer(void) {
delay(1); // Why needed?? <<<<<<<<<<<<<<
return (uartWriteIndex - uartReadIndex);
}
// Read UART data returns a pointer to the uartData structure.
// This increments the index and thus can only be called once per
// successful UART output word. If no data is available, a NULL
// pointer is returned.
struct uartData* readUartData(void) {
if(uartReadIndex >= uartWriteIndex) // Never should be greater
return NULL;
int32_t uri = uartReadIndex & uartDMask;
// Circular increment of the read index
uartReadIndex++;
bufferSpace = 16 - uartWriteIndex + uartReadIndex;
return &uartD[uri];
}
// The input is a floating point value, centered on 0.0. One source of this
// could be a discriminator base-band output. If the input signal is offset
// from zero, it can be corrected with this function. This inputOffset is
// added to the input and can be + or - in value.
void setInputOffset(float32_t _inputOffset) {
inputOffset = _inputOffset;
}
void setSampleRate_Hz(float32_t _sampleRate_Hz) {
sampleRate_Hz = _sampleRate_Hz;
}
virtual void update(void);
private:
// One input data pointer
audio_block_f32_t *inputQueueArray_f32[1];
float32_t sampleRate_Hz = AUDIO_SAMPLE_RATE_EXACT;
uint16_t block_size = AUDIO_BLOCK_SAMPLES;
// BFSK decode clock variables
// Always 1 start bit.
uint16_t nBits = 8; // Data bits
uint16_t nParity = PARITY_NONE;
uint16_t nStop = 1; // Fixed for now
uint16_t nTotal = 9; // 1+nBits+Parity
uint32_t cTauI = 40UL;
uint32_t cTauHalfI = 20UL;
struct uartData uartD[16]; // Circular buffer of UART data
float32_t inputOffset = 0.0f; // Offset of input data
// These next 2 indices are the index, mod 16, where we wil write
// data to next, or read data from next (if available).
// If the two are equal, no data is available to read.
int32_t uartReadIndex = 0L; // Both indices continue to grow, unbounded
int32_t uartWriteIndex = 0L;
const int32_t uartDMask = 0B1111; // Mask for 16 word buffer
int32_t bufferSpace = 16L; // 16 - uartWriteIndex + uartReadIndex
uint16_t serialState = SERIAL_IDLE;
uint8_t saveStatus;
float32_t yData = 0.0f;
float32_t yLast = -0.01f;
float32_t yClock = -1.0f;
float32_t errorClock = 0.0f;
uint32_t sClock = 0UL; // Counted in audio sample units
uint32_t lastTime = 0UL; // Last zero crossing
uint32_t timeStartBit= 0UL;
uint32_t timeLastTransition = 0UL;
uint32_t cSampleNext = 0UL;
uint8_t bitCount = 0UL; // Where we are at in receiving word
uint32_t bitMask = 1; // Values 1, 2, 4, 8, 16,... tracks bitCount
uint32_t dataWord = 0UL;
uint32_t elapsedTime = 0UL;
void initUartData(uint n) {
uartD[n].data = 0UL;
uartD[n].status = 0; // including data ready, overrun, parity and framing errors
uartD[n].timeCrossings = 0;
}
// Write an output word for Serial BFSK modem
void writeUartData(uint32_t _data, uint8_t _status, int32_t _timeCrossings) {
bufferSpace = 16L - uartWriteIndex + uartReadIndex; //0 to 16 amount of space available
if(bufferSpace > 0)
{
uartD[uartWriteIndex&uartDMask].data = _data;
uartD[uartWriteIndex&uartDMask].status = _status;
uartD[uartWriteIndex&uartDMask].timeCrossings = _timeCrossings;
uartWriteIndex++; // Bump write index
saveStatus &= ~ERR_OVERRUN; // Clear overrun bit, it has finally been sent
}
else // No room in buffer
{
saveStatus |= ERR_OVERRUN; // Error gets sent when overrun is cleared
}
bufferSpace = 16L - uartWriteIndex + uartReadIndex;
}
// Thanks svicent. NEEDS TO BE ADDED TO writeUartData() <<<----
uint8_t oddParity(uint32_t ino) {
uint8_t n8 = 0;
while(ino != 0)
{
n8++;
ino &= (ino-1); // the loop will execute once for each bit of ino set
}
/* if n8 is odd, least significant bit will be 1 */
return (n8 & 1);
}
}; // End class UART_F32
#endif