/* * radioBFSKmodulator_F32 * * Created: Bob Larkin 17 March 2022 * * License: MIT License. Use at your own risk. See corresponding .h file. * * 2 April 2023 -Corrected to handle outputs from a full buffer. RSL * Added int16_t getBufferSpace(). RSL */ #include "radioBFSKmodulator_F32.h" // 513 values of the sine wave in a float array: #include "sinTable512_f32.h" // 64 entry send buffer check. Sets stateBuffer // Returns the number of un-transmitted characters. int16_t RadioBFSKModulator_F32::checkBuffer(void) { int64_t deltaIndex = indexIn - indexOut; if(deltaIndex==0LL) stateBuffer = DATA_BUFFER_EMPTY; else if(deltaIndex==64LL) stateBuffer = DATA_BUFFER_FULL; else stateBuffer = DATA_BUFFER_PART; if(deltaIndex<0LL || deltaIndex>64LL) // Should never happen { Serial.print("ERROR in Buffer; deltaIndex = "); Serial.println(deltaIndex); } return (int16_t)deltaIndex; } void RadioBFSKModulator_F32::update(void) { audio_block_f32_t *blockFSK; uint16_t index, i; float32_t vca; float32_t a, b; // uint32_t tt=micros(); blockFSK = AudioStream_F32::allocate_f32(); // Get the output block if (!blockFSK) return; for (i=0; i < blockFSK->length; i++) { samplePerBitCount++; // Each data bit is an integer number of sample periods if(samplePerBitCount >= samplesPerDataBit) // Bit transition time { samplePerBitCount = 0; // Wait a bit period before checking again if(bitSendCount < numBits) // Still sending a word, get next bit { vc = (uint16_t)(currentWord & 1); // Send 0 or 1 currentWord = currentWord >> 1; // Next bit position bitSendCount++; } else // End of word, get another if possible { if(stateBuffer != DATA_BUFFER_EMPTY) { indexOut++; // Just keeps on going, not circular checkBuffer(); currentWord = dataBuffer[indexOut&indexMask]; // Serial.print(indexIn); // Serial.print(" In Out "); // Serial.println(indexOut); vc = (uint16_t)(currentWord & 1); // Bit to send next bitSendCount = 1U; // Count how many bits have been sent currentWord = currentWord >> 1; } else // No word available { vc = 1; //Idle at logic 1 (Make programmable?) } } // end, get another word } // end, bit transition time if(FIRcoeff==NULL) // No LPF being used vca = (float32_t)vc; else { // Put latest data point intoFIR LPF buffer indexFIRlatest++; FIRdata[indexFIRlatest & indexFIRMask] = (float32_t)vc; // Add to buffer // Optional FIR LPF vca = 0.0f; int16_t iiBase16 = (int16_t)(indexFIRlatest & indexFIRMask); int16_t iiSize = (int16_t)(indexFIRMask + 1ULL); for(int16_t k=0; k 512.0f) currentPhase -= 512.0f; index = (uint16_t) currentPhase; float32_t deltaPhase = currentPhase - (float32_t)index; /* Read two nearest values of input value from the sin table */ a = sinTable512_f32[index]; b = sinTable512_f32[index+1]; blockFSK->data[i] = magnitude*(a+(b-a)*deltaPhase); // Linear interpolation samplePerBitCount++; } AudioStream_F32::transmit(blockFSK); AudioStream_F32::release (blockFSK); // Serial.print(" "); Serial.println(micros()-tt); }