More commenting
This commit is contained in:
parent
a6bad60233
commit
fd4e7fb4bc
90
Modem/afsk.c
90
Modem/afsk.c
|
@ -282,16 +282,48 @@ void afsk_adc_isr(Afsk *afsk, int8_t currentSample) {
|
||||||
afsk->iirY[0] = afsk->iirY[1];
|
afsk->iirY[0] = afsk->iirY[1];
|
||||||
afsk->iirY[1] = afsk->iirX[0] + afsk->iirX[1] + (afsk->iirY[0] >> 1);
|
afsk->iirY[1] = afsk->iirX[0] + afsk->iirX[1] + (afsk->iirY[0] >> 1);
|
||||||
|
|
||||||
// Put the sampled bit in a delay-line
|
// We put the sampled bit in a delay-line:
|
||||||
afsk->sampledBits <<= 1; // Bitshift everything 1 left
|
// First we bitshift everything 1 left
|
||||||
|
afsk->sampledBits <<= 1;
|
||||||
|
// And then add the sampled bit to our delay line
|
||||||
afsk->sampledBits |= (afsk->iirY[1] > 0) ? 1 : 0;
|
afsk->sampledBits |= (afsk->iirY[1] > 0) ? 1 : 0;
|
||||||
|
|
||||||
// Put the current raw sample in the delay FIFO
|
// Put the current raw sample in the delay FIFO
|
||||||
fifo_push(&afsk->delayFifo, currentSample);
|
fifo_push(&afsk->delayFifo, currentSample);
|
||||||
|
|
||||||
// If there is a signal transition, recalibrate
|
// We need to check whether there is a signal transition.
|
||||||
// sampling phase
|
// If there is, we can recalibrate the phase of our
|
||||||
|
// sampler to stay in sync with the transmitter. A bit of
|
||||||
|
// explanation is required to understand how this works.
|
||||||
|
// Since we have PHASE_MAX/PHASE_BITS = 8 samples per bit,
|
||||||
|
// we employ a phase counter (currentPhase), that increments
|
||||||
|
// by PHASE_BITS everytime a sample is captured. When this
|
||||||
|
// counter reaches PHASE_MAX, it wraps around by modulus
|
||||||
|
// PHASE_MAX. We then look at the last three samples we
|
||||||
|
// captured and determine if the bit was a one or a zero.
|
||||||
|
//
|
||||||
|
// This gives us a "window" looking into the stream of
|
||||||
|
// samples coming from the ADC. Sort of like this:
|
||||||
|
//
|
||||||
|
// Past Future
|
||||||
|
// 0000000011111111000000001111111100000000
|
||||||
|
// |________|
|
||||||
|
// ||
|
||||||
|
// Window
|
||||||
|
//
|
||||||
|
// Every time we detect a signal transition, we adjust
|
||||||
|
// where this window is positioned little. How much we
|
||||||
|
// adjust it is defined by PHASE_INC. If our current phase
|
||||||
|
// phase counter value is less than half of PHASE_MAX (ie,
|
||||||
|
// the window size) when a signal transition is detected,
|
||||||
|
// add PHASE_INC to our phase counter, effectively moving
|
||||||
|
// the window a little bit backward (to the left in the
|
||||||
|
// illustration), inversely, if the phase counter is greater
|
||||||
|
// than half of PHASE_MAX, we move it forward a little.
|
||||||
|
// This way, our "window" is constantly seeking to position
|
||||||
|
// it's center at the bit transitions. Thus, we synchronise
|
||||||
|
// our timing to the transmitter, even if it's timing is
|
||||||
|
// a little off compared to our own.
|
||||||
if (TRANSITION_FOUND(afsk->sampledBits)) {
|
if (TRANSITION_FOUND(afsk->sampledBits)) {
|
||||||
if (afsk->currentPhase < PHASE_THRESHOLD) {
|
if (afsk->currentPhase < PHASE_THRESHOLD) {
|
||||||
afsk->currentPhase += PHASE_INC;
|
afsk->currentPhase += PHASE_INC;
|
||||||
|
@ -299,18 +331,25 @@ void afsk_adc_isr(Afsk *afsk, int8_t currentSample) {
|
||||||
afsk->currentPhase -= PHASE_INC;
|
afsk->currentPhase -= PHASE_INC;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// We incroment our phase counter
|
||||||
afsk->currentPhase += PHASE_BITS;
|
afsk->currentPhase += PHASE_BITS;
|
||||||
|
|
||||||
// Look at the raw samples to determine the transmitted bit
|
// Check if we have reached the end of
|
||||||
|
// our sampling window.
|
||||||
if (afsk->currentPhase >= PHASE_MAX) {
|
if (afsk->currentPhase >= PHASE_MAX) {
|
||||||
|
// If we have, wrap around our phase
|
||||||
|
// counter by modulus
|
||||||
afsk->currentPhase %= PHASE_MAX;
|
afsk->currentPhase %= PHASE_MAX;
|
||||||
|
|
||||||
// Bitshift to make room for next bit
|
// Bitshift to make room for the next
|
||||||
|
// bit in our stream of demodulated bits
|
||||||
afsk->actualBits <<= 1;
|
afsk->actualBits <<= 1;
|
||||||
|
|
||||||
// Determine the actual bit value by reading the last
|
// We determine the actual bit value by reading
|
||||||
// 3 sampled bits. If there is two ore more 1's, the
|
// the last 3 sampled bits. If there is two or
|
||||||
// actual bit is a 1, otherwise a 0.
|
// more 1's, we will assume that the transmitter
|
||||||
|
// sent us a one, otherwise we assume a zero
|
||||||
uint8_t bits = afsk->sampledBits & 0x07;
|
uint8_t bits = afsk->sampledBits & 0x07;
|
||||||
if (bits == 0x07 || // 111
|
if (bits == 0x07 || // 111
|
||||||
bits == 0x06 || // 110
|
bits == 0x06 || // 110
|
||||||
|
@ -321,9 +360,22 @@ void afsk_adc_isr(Afsk *afsk, int8_t currentSample) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now we can pass the actual bit to the HDLC parser.
|
// Now we can pass the actual bit to the HDLC parser.
|
||||||
// We are using NRZI coding, so if 2 consecutive bits
|
// We are using NRZ coding, so if 2 consecutive bits
|
||||||
// have the same value, we have a 1, otherwise a 0.
|
// have the same value, we have a 1, otherwise a 0.
|
||||||
// We use the EDGE_FOUND function to determine this.
|
// We use the TRANSITION_FOUND function to determine this.
|
||||||
|
//
|
||||||
|
// This is smart in combination with bit stuffing,
|
||||||
|
// since it ensures a transmitter will never send more
|
||||||
|
// than five consecutive 1's. When sending consecutive
|
||||||
|
// ones, the signal stays at the same level, and if
|
||||||
|
// this happens for longer periods of time, we would
|
||||||
|
// not be able to synchronize our phase to the transmitter
|
||||||
|
// and would start experiencing "bit slip".
|
||||||
|
//
|
||||||
|
// By combining bit-stuffing with NRZ coding, we ensure
|
||||||
|
// that the signal will regularly make transitions
|
||||||
|
// that we can use to synchronize our phase.
|
||||||
|
//
|
||||||
// We also check the return of the Link Control parser
|
// We also check the return of the Link Control parser
|
||||||
// to check if an error occured.
|
// to check if an error occured.
|
||||||
if (!hdlcParse(&afsk->hdlc, !TRANSITION_FOUND(afsk->actualBits), &afsk->rxFifo)) {
|
if (!hdlcParse(&afsk->hdlc, !TRANSITION_FOUND(afsk->actualBits), &afsk->rxFifo)) {
|
||||||
|
@ -337,7 +389,7 @@ void afsk_adc_isr(Afsk *afsk, int8_t currentSample) {
|
||||||
//////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////
|
||||||
|
|
||||||
// Defines how many consecutive ones we send
|
// Defines how many consecutive ones we send
|
||||||
// before we need "stuff" in a zero
|
// before we need to "stuff" in a zero
|
||||||
#define BIT_STUFF_LEN 5
|
#define BIT_STUFF_LEN 5
|
||||||
|
|
||||||
// A macro for switching what tone is being
|
// A macro for switching what tone is being
|
||||||
|
@ -528,11 +580,14 @@ void afsk_init(Afsk *afsk, int _adcPin) {
|
||||||
// Allocate memory for struct
|
// Allocate memory for struct
|
||||||
memset(afsk, 0, sizeof(*afsk));
|
memset(afsk, 0, sizeof(*afsk));
|
||||||
|
|
||||||
// Configure pins
|
// Configure ADC pin
|
||||||
afsk->adcPin = _adcPin;
|
afsk->adcPin = _adcPin;
|
||||||
|
|
||||||
|
// Initialise phase increment to that
|
||||||
|
// of the mark frequency
|
||||||
afsk->phaseInc = MARK_INC;
|
afsk->phaseInc = MARK_INC;
|
||||||
|
|
||||||
// Init FIFO buffers
|
// Initialize FIFO buffers
|
||||||
fifo_init(&afsk->delayFifo, (uint8_t *)afsk->delayBuf, sizeof(afsk->delayBuf));
|
fifo_init(&afsk->delayFifo, (uint8_t *)afsk->delayBuf, sizeof(afsk->delayBuf));
|
||||||
fifo_init(&afsk->rxFifo, afsk->rxBuf, sizeof(afsk->rxBuf));
|
fifo_init(&afsk->rxFifo, afsk->rxBuf, sizeof(afsk->rxBuf));
|
||||||
fifo_init(&afsk->txFifo, afsk->txBuf, sizeof(afsk->txBuf));
|
fifo_init(&afsk->txFifo, afsk->txBuf, sizeof(afsk->txBuf));
|
||||||
|
@ -542,12 +597,15 @@ void afsk_init(Afsk *afsk, int _adcPin) {
|
||||||
fifo_push(&afsk->delayFifo, 0);
|
fifo_push(&afsk->delayFifo, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Init DAC & ADC
|
// Initialize hardware
|
||||||
AFSK_ADC_INIT(_adcPin, afsk);
|
AFSK_ADC_INIT(_adcPin, afsk);
|
||||||
AFSK_DAC_INIT();
|
AFSK_DAC_INIT();
|
||||||
LED_TX_INIT();
|
LED_TX_INIT();
|
||||||
LED_RX_INIT();
|
LED_RX_INIT();
|
||||||
|
|
||||||
|
// And register the modem file-pointer
|
||||||
|
// functions for reading from and
|
||||||
|
// writing to it.
|
||||||
DB(afsk->fd._type = KFT_AFSK);
|
DB(afsk->fd._type = KFT_AFSK);
|
||||||
afsk->fd.write = afsk_write;
|
afsk->fd.write = afsk_write;
|
||||||
afsk->fd.read = afsk_read;
|
afsk->fd.read = afsk_read;
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
#define VERS_BUILD 382
|
#define VERS_BUILD 383
|
||||||
#define VERS_HOST "vixen"
|
#define VERS_HOST "vixen"
|
||||||
|
|
Loading…
Reference in New Issue