The steps for single-sideband modulation are hashed out, but the actual sampling of audio is not implemented yet
chibios
Marshal Horn 2020-07-22 08:15:19 -07:00
rodzic 55ad088791
commit 9c5011542d
4 zmienionych plików z 61 dodań i 14 usunięć

Wyświetl plik

@ -23,7 +23,7 @@ int32_t hilbert19(int16_t * src){
return sum;
}
int32_t hilbert32(int16_t * src, uint8_t i){
int32_t diff32(int16_t * src, uint8_t i){
i -= 16; // Move to the center of the history
const uint8_t mask = 32-1;
/* Hilbert coeffecients with a hamming window
@ -42,3 +42,18 @@ int32_t hilbert32(int16_t * src, uint8_t i){
sum += (src[(i-15)&mask]-src[(i+15)&mask]) * (int32_t)coef[7];
return sum;
}
int32_t hilbert32(int16_t * src, uint8_t i){
i -= 16; // Move to the center of the history
const uint8_t mask = 32-1;
/* Differentiation coeffecients with a hamming window
* Values are -1, 1/2, -1/3, 1/4, etc
* Stored in 15.16 fixed-point
*/
const int16_t coef[] = {-4055,1967,-1245,868,-631,466,-344,252,-181,127,-86,57,-38,26,-22};
int32_t sum = 0;
for(uint8_t j = 0; j<15; ++i){
sum += (src[(i-1-j)&mask]-src[(i+1+j)&mask]) * (int32_t)coef[j];
}
return sum;
}

Wyświetl plik

@ -13,5 +13,15 @@ int32_t hilbert19(int16_t * src);
* This implementation assumes a 32-element buffer, and wraps accordingly
* @param src The source data. Make sure I and Q are not interlieved
* @param i The index of the latest element. Older elements are assumed to have decreasing index.
* @returns The input signal, delayed by 90 degrees (The imaginary component).
*/
int32_t hilbert32(int16_t * src, uint8_t i);
/** 31-element differentiation
*
* This implementation assumes a 32-element buffer, and wraps accordingly
* @param src The source data. Make sure I and Q are not interlieved
* @param i The index of the latest element. Older elements are assumed to have decreasing index.
* @returns the derivative of the input
*/
int32_t diff32(int16_t * src, uint8_t i);

Wyświetl plik

@ -7,6 +7,7 @@
#include "ssb.h"
#include "hilbert.h"
#include "../drivers/speaker.h"
#include "../trig.h"
msg_t ssb_rx(mailbox_t * inbox, enum radio_mode * mode){
union complex c;
@ -14,7 +15,7 @@ msg_t ssb_rx(mailbox_t * inbox, enum radio_mode * mode){
int16_t real[len];
int16_t imag[len];
while((USB==*mode) || (LSB==*mode)){
for( int i=0; i<len;){
for( int i=0; i<len; ++i){
/** Fetch new data */
msg_t m = chMBFetchTimeout(inbox, &c.msg, TIME_MS2I(10));
if(MSG_OK != m)
@ -41,16 +42,36 @@ msg_t ssb_rx(mailbox_t * inbox, enum radio_mode * mode){
return MSG_OK;
}
const int32_t fscale = 1; //FIXME
void ssb_tx(int16_t * amp, int32_t * freq, int16_t * src, size_t qty){
// Source data is single-channel audio
int32_t f = freq[0];
for(size_t i = 0; i < (qty-18); ++i){
amp[i]=src[i+9];
// FIXME: Subtraction is not a differentiator
// Maybe the differentiation can be combined with the hilbert?
f -= hilbert19(src+i) * fscale;
freq[i]=f;
msg_t ssb_tx(mailbox_t * inbox, enum radio_mode * mode, struct synth * txclk){
union complex c;
const int len = 32;
const int sample_rate = 5000;
int16_t raw[len];
int16_t phase[len];
while((USB==*mode) || (LSB==*mode)){
for( int i=0; i<len; ++i){
/** Fetch new data */
msg_t m = chMBFetchTimeout(inbox, &c.msg, TIME_MS2I(10));
if(MSG_OK != m)
return m;
raw[i] = c.real;
/** Process the received data */
int16_t imag = hilbert32(raw, i)>>16;
if(LSB==*mode)
imag=-imag;
uint8_t j = (i-16)&31; // Match group delay of Hilbert transform
int16_t real = raw[j]; //TODO: Match frequency response of Hilbert transform
phase[i]=arctan3(imag, real);
int16_t amp=magn(imag, real);
int32_t freq = diff32(phase,i);
freq *= sample_rate;
/** Update the outputs
* TODO: Fix amplitude based on frequency
* TODO: Update DAC more frequently than si5351. Use DMA
*/
synthSetBaseband(txclk, freq);
dacPutChannelX(&DACD1, 1, amp);
}
}
return MSG_OK;
}

Wyświetl plik

@ -7,6 +7,7 @@
#include <stdint.h>
#include <stddef.h>
#include "rx.h"
#include "../drivers/si5351.h"
/** Single sideband decoder
*
@ -16,4 +17,4 @@ msg_t ssb_rx(mailbox_t * inbox, enum radio_mode * mode);
/** Singgle sideband encoder
*
*/
void ssb_tx(int16_t * amp, int32_t * freq, int16_t * src, size_t qty);
msg_t ssb_tx(mailbox_t * inbox, enum radio_mode * mode, struct synth * txclk);