/* * radioFT8modulator_F32 * * Created: Bob Larkin 17 July 2022 * * License: MIT License. Use at your own risk. See radioFT8Modulator.h file. * */ #include "radioFT8Modulator_F32.h" // 513 values of the sine wave in a float array: #include "sinTable512_f32.h" void RadioFT8Modulator_F32::update(void) { audio_block_f32_t *blockOut; uint16_t index; float32_t a, b; float32_t mag = 1.0f; // uint32_t tu = micros(); if(ft8Transmit==false) return; // Sending tones. Sort out actions blockOut = AudioStream_F32::allocate_f32(); // Get the output block if (!blockOut) return; /* NOTE - ALL FT8 values shown in comments below are for a 48 kHz sample rate * tone81SendCount 0 to 80 (81 tones) * audioSampleCount 0 to 7679 for 48kHz sample rate * sampleSent 0 to 622079 for 48kHz, 12.96 seconds, 81 tones */ // Send 128 audio samples of FSK sine waves for(int kk=0; kk<128; kk++) { audioSampleCount = sampleSent % toneLength; // audioSampleCount is always derived from sampleSent mag = magnitude; // Use down below dphi = phaseIncrement; if(tone81SendCount>0 && tone81SendCount<80) // Exclude end tones as special cases { if(audioSampleCount=pulseSegActive && audioSampleCount<(toneLength - pulseSegActive)) // Center region, no pulses involved { // Center of tone with pulse level at 1.0, main tone, 2816 to 4863 dphi += tones[tone81SendCount]*dphi_peak; } else //if((audioSampleCount - 1)>(toneLength - pulseSegActive)) // Last part of tone with pulse shaping { // Current tone with pulse falling 1.0 to 0.500391960, audioSampleCount 4864 to 7679 dphi += (1.0f - pulse[audioSampleCount - (toneLength - pulseSegActive)])*tones[tone81SendCount]*dphi_peak; // plus overlap from next tone with pulse rising 0.0 to 0.499608070, audioSampleCount 4864 to 7679 dphi += (pulse[audioSampleCount - (toneLength - pulseSegActive)])*tones[tone81SendCount + 1]*dphi_peak; } } // End of middle 79 tones else if(tone81SendCount==0) // Key click pulse with no tone ahead { if((audioSampleCount)<(toneLength - pulseSegActive)) // audioSampleCount 0 to 4863 incl or 4864 points { // Pulse level at 1.0, main tone dphi += tones[0]*dphi_peak; } else // Last part of tone with pulse shaping { // Current tone with pulse falling 1.0 to 0.50039196, audioSampleCount 4864 to 7679 or 2816 pts dphi += (1.0f - pulse[audioSampleCount -(toneLength - pulseSegActive)])*tones[0]*dphi_peak; // plus overlap from next tone with pulse rising 0.00000003 to 0.49960807 on 4864 to 7679 dphi += (pulse[audioSampleCount - (toneLength - pulseSegActive)])*tones[1]*dphi_peak; } if(audioSampleCount=pulseSegActive) // Rest of region, no pulses involved { // Rest of tone with pulse level at 1.0, main tone, audioSampleCount 2816 to 7679 dphi += tones[80]*dphi_peak; } if(audioSampleCount>(toneLength - cosineRampActive)) { mag = magnitude*ramp[toneLength - audioSampleCount]; } else mag = magnitude; } // End of last tone currentPhase += dphi; while(currentPhase > 512.0f) currentPhase -= 512.0f; while(currentPhase < 0.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]; blockOut->data[kk] = mag*(a+(b-a)*deltaPhase); // Linear interpolation sampleSent++; audioSampleCount = sampleSent % toneLength; if(audioSampleCount == 0) // End of a tone send { if(++tone81SendCount == 81) // End of the 12.96 second period { tone81SendCount = 0; ft8Transmit = false; // Serial.println("End Transmission"); } } } // End, over all 128 audio output points AudioStream_F32::transmit(blockOut); AudioStream_F32::release (blockOut); // Serial.println(micros() - tu); }