diff --git a/Modem/afsk.c b/Modem/afsk.c index d359efc..423798d 100644 --- a/Modem/afsk.c +++ b/Modem/afsk.c @@ -6,8 +6,7 @@ #include "config.h" // This stores basic configuration #include "hardware.h" // Hardware functions are nice to have too :) -#include // Timer driver from BertOS -//FIXME: is this needed ? #include +#include // Timer driver from BertOS #include // Power management from BertOS #include // Access to PROGMEM from BertOS @@ -79,16 +78,30 @@ INLINE uint8_t sinSample(uint16_t i) { // bits in a stream and returns true if they differ. #define TRANSITION_FOUND(bits) BITS_DIFFER((bits), (bits) >> 1) +// We use this macro to check if the signal transitioned +// from one bit (tone) to another. This is used in the phase +// synchronisation. We look at the last four bits in the +// stream of demodulated bits and if they differ in sets of +// two bits, we assume a signal transition occured. We look +// at pairs of bits to eliminate false positives where a +// single erroneously demodulated bit will trigger an +// incorrect phase syncronisation. +#define DUAL_XOR(bits1, bits2) ((((bits1)^(bits2)) & 0x03) == 0x03) +#define SIGNAL_TRANSITIONED(bits) DUAL_XOR((bits), (bits) >> 2) + // Phase sync constants -#define PHASE_BITS 8 -#define PHASE_INC 1 // FIXME: originally 1 -#define PHASE_MAX (SAMPLESPERBIT * PHASE_BITS) -#define PHASE_THRESHOLD (PHASE_MAX / 4) // FIXME: originally /2 +#define PHASE_BITS 8 // How much to increment phase counter each sample +#define PHASE_INC 1 // Nudge by an eigth of a sample each adjustment +#define PHASE_MAX (SAMPLESPERBIT * PHASE_BITS) // Resolution of our phase counter = 64 +#define PHASE_THRESHOLD (PHASE_MAX / 4) // Target transition point of our phase window // Modulation constants -#define MARK_FREQ 1200 +#define MARK_FREQ 1200 // The tone frequency signifying a binary one +#define SPACE_FREQ 2200 // The tone frequency signifying a binary zero + +// We calculate the amount we need to increment the index +// in our sine table for each sample of the two tones #define MARK_INC (uint16_t)(DIV_ROUND(SIN_LEN * (uint32_t)MARK_FREQ, CONFIG_AFSK_DAC_SAMPLERATE)) -#define SPACE_FREQ 2200 #define SPACE_INC (uint16_t)(DIV_ROUND(SIN_LEN * (uint32_t)SPACE_FREQ, CONFIG_AFSK_DAC_SAMPLERATE)) // HDLC flag bytes @@ -111,7 +124,6 @@ STATIC_ASSERT(!(CONFIG_AFSK_DAC_SAMPLERATE % BITRATE)); // Link Layer Control and Demodulation // ////////////////////////////////////////////////////// -static int adjustCount; // FIXME: Debug // hdlcParse ///////////////////////////////////////// // This function looks at the raw bits demodulated from // the physical medium and tries to parse actual data @@ -158,7 +170,6 @@ static bool hdlcParse(Hdlc *hdlc, bool bit, FIFOBuffer *fifo) { // false and stopping the here. ret = false; hdlc->receiving = false; - kprintf("RX overrun 1!"); // FIXME: remove these LED_RX_OFF(); } @@ -169,8 +180,6 @@ static bool hdlcParse(Hdlc *hdlc, bool bit, FIFOBuffer *fifo) { // of the received bytes. hdlc->currentByte = 0; hdlc->bitIndex = 0; - //if (adjustCount > 25) kprintf("[AC%d]", adjustCount); // this slows down stuff and makes it work. wtf?! - adjustCount = 0; return ret; } @@ -242,7 +251,6 @@ static bool hdlcParse(Hdlc *hdlc, bool bit, FIFOBuffer *fifo) { // If it is, abort and return false hdlc->receiving = false; LED_RX_OFF(); - kprintf("RX overrun 3!"); ret = false; } } @@ -255,7 +263,6 @@ static bool hdlcParse(Hdlc *hdlc, bool bit, FIFOBuffer *fifo) { // If it is, well, you know by now! hdlc->receiving = false; LED_RX_OFF(); - kprintf("RX overrun 4!"); ret = false; } @@ -339,8 +346,7 @@ void afsk_adc_isr(Afsk *afsk, int8_t currentSample) { // 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)) { - adjustCount++; + if (SIGNAL_TRANSITIONED(afsk->sampledBits)) { if (afsk->currentPhase < PHASE_THRESHOLD) { afsk->currentPhase += PHASE_INC; } else { @@ -363,27 +369,29 @@ void afsk_adc_isr(Afsk *afsk, int8_t currentSample) { afsk->actualBits <<= 1; // We determine the actual bit value by reading - // the last 3 sampled bits. If there is two or + // the last 5 sampled bits. If there is three or // more 1's, we will assume that the transmitter // sent us a one, otherwise we assume a zero - // FIXME: Increasing this to 5 bit determine - uint8_t bits = afsk->sampledBits & 0x07; - if (bits == 0x07 || // 111 - bits == 0x06 || // 110 - bits == 0x05 || // 101 - bits == 0x03 // 011 - ) { - afsk->actualBits |= 1; - } - // uint8_t bits = afsk->sampledBits & 0x0f; - // uint8_t c = 0; - // c += bits & BV(1); - // c += bits & BV(2); - // c += bits & BV(3); - // c += bits & BV(4); - // c += bits & BV(5); - // if (c >= 3) afsk->actualBits |= 1; + uint8_t bits = afsk->sampledBits & 0x0f; + uint8_t c = 0; + c += bits & BV(1); + c += bits & BV(2); + c += bits & BV(3); + c += bits & BV(4); + c += bits & BV(5); + if (c >= 3) afsk->actualBits |= 1; + + //// Alternative using only three bits ////////// + // uint8_t bits = afsk->sampledBits & 0x07; + // if (bits == 0x07 || // 111 + // bits == 0x06 || // 110 + // bits == 0x05 || // 101 + // bits == 0x03 // 011 + // ) { + // afsk->actualBits |= 1; + // } + ///////////////////////////////////////////////// // Now we can pass the actual bit to the HDLC parser. // We are using NRZ coding, so if 2 consecutive bits @@ -420,14 +428,17 @@ void afsk_adc_isr(Afsk *afsk, int8_t currentSample) { #define BIT_STUFF_LEN 5 // A macro for switching what tone is being -// synthesized by the DAC. +// synthesized by the DAC. We basically just +// change how quickly we go through the sine +// table each time we send out a sample. This +// is done by changing the phaseInc variable #define SWITCH_TONE(inc) (((inc) == MARK_INC) ? SPACE_INC : MARK_INC) // This function starts the transmission static void afsk_txStart(Afsk *afsk) { if (!afsk->sending) { // Initialize the phase increment to - // that of the mark frequency + // that of the mark frequency (zero) afsk->phaseInc = MARK_INC; // Reset the phase accumulator to 0 afsk->phaseAcc = 0; diff --git a/Modem/config.h b/Modem/config.h index d032a76..a88d5d0 100644 --- a/Modem/config.h +++ b/Modem/config.h @@ -11,7 +11,7 @@ #define CONFIG_AFSK_RXTIMEOUT 0 // How long a read operation from the modem // will wait for data before timing out. -#define CONFIG_AFSK_PREAMBLE_LEN 350UL // The length of the packet preamble in milliseconds +#define CONFIG_AFSK_PREAMBLE_LEN 450UL // The length of the packet preamble in milliseconds #define CONFIG_AFSK_TRAILER_LEN 100UL // The length of the packet tail in milliseconds #endif \ No newline at end of file diff --git a/Modem/hardware.c b/Modem/hardware.c index 949dd5c..3b12fb7 100644 --- a/Modem/hardware.c +++ b/Modem/hardware.c @@ -17,6 +17,10 @@ static Afsk *modem; // And now for the actual hardware functions // ////////////////////////////////////////////////////// +// M1 correction = 9500 +// M2 correction = 40000 +#define FREQUENCY_CORRECTION 0 + // This function initializes the ADC and configures // it the way we need. void hw_afsk_adcInit(int ch, Afsk *_modem) @@ -28,15 +32,19 @@ void hw_afsk_adcInit(int ch, Afsk *_modem) // a pin that can't be used for analog input ASSERT(ch <= 5); - // We need to do some configuration on the Timer/Counter Control - // Register 1, aka Timer1 + // We need a timer to control how often our sampling functions + // should run. To do this we will need to change some registers. + // First we do some configuration on the Timer/Counter Control + // Register 1, aka Timer1. + // // The following bits are set: - // CS11: ClockSource 11, sets the prescaler to 8, ie 2MHz - // WGM13 and WGM12 together enables Timer Mode 12, which + // CS10: ClockSource 10, sets no prescaler on the clock, + // meaning it will run at the same speed as the CPU, ie 16MHz + // WGM13 and WGM12 together enables "Timer Mode 12", which // is Clear Timer on Compare, compare set to TOP, and the // source for the TOP value is ICR1 (Input Capture Register1). TCCR1A = 0; - TCCR1B = BV(CS11) | BV(WGM13) | BV(WGM12); + TCCR1B = BV(CS10) | BV(WGM13) | BV(WGM12); // Then we set the ICR1 register to what count value we want to // reset (and thus trigger the interrupt) at. @@ -47,7 +55,8 @@ void hw_afsk_adcInit(int ch, Afsk *_modem) // (CPUClock / Prescaler) / desired frequency - 1 // So that's what well put in this register to set up our // 9.6KHz sampling rate. - ICR1 = ((CPU_FREQ / 8) / 9600) - 1; + ICR1 = (((CPU_FREQ+FREQUENCY_CORRECTION)) / 9600) - 1; + kprintf("ICR1=%d",ICR1); // Set reference to AVCC (5V), select pin // Set the ADMUX register. The first part (BV(REFS0)) sets diff --git a/Modem/main.c b/Modem/main.c index 6b88dd6..602d978 100644 --- a/Modem/main.c +++ b/Modem/main.c @@ -29,7 +29,8 @@ static Serial ser; // Declare a serial interface struct #define TEST_TX false // Whether we should send test packets // periodically, plus what to send: -#define TEST_PACKET "Test MP1 AFSK Packet. Test123" +#define TEST_PACKET "Test MP1 AFSK Packet. Test123." +#define TEST_TX_INTERVAL 10000L static uint8_t serialBuffer[MP1_MAX_FRAME_LENGTH]; // This is a buffer for incoming serial data @@ -47,8 +48,8 @@ static bool sertx = false; // Flag signifying whether it's time to send da // so we can process each packet as they are decoded. // Right now it just prints the packet to the serial port. static void mp1Callback(struct MP1Packet *packet) { - //kfile_printf(&ser.fd, "%.*s\r\n", packet->dataLength, packet->data); - kprintf("%.*s\n", packet->dataLength, packet->data); + kfile_printf(&ser.fd, "%.*s\n", packet->dataLength, packet->data); + //kprintf("%.*s\n", packet->dataLength, packet->data); } // Simple initialization function. @@ -57,8 +58,7 @@ static void init(void) // Enable interrupts IRQ_ENABLE; // Initialize BertOS debug bridge - kdbg_init(); - kprintf("Init\n"); + // kdbg_init(); // Initialize hardware timers timer_init(); @@ -103,7 +103,6 @@ int main(void) // and the byte is not a "transmit" (newline) character, // we should store it for transmission. if ((serialLen < MP1_MAX_FRAME_LENGTH) && (sbyte != 138)) { - //kprintf("Byte: %d\n", sbyte); // FIXME: delete // Put the read byte into the buffer; serialBuffer[serialLen] = sbyte; // Increment the read length counter @@ -127,7 +126,7 @@ int main(void) } // Periodically send test data if we should do so - if (TEST_TX && timer_clock() - start > ms_to_ticks(5000L)) { + if (TEST_TX && timer_clock() - start > ms_to_ticks(TEST_TX_INTERVAL)) { // Reset the timer counter; start = timer_clock(); // And send a test packet! diff --git a/Modem/protocol/mp1.c b/Modem/protocol/mp1.c index 4d29f53..c8d1017 100644 --- a/Modem/protocol/mp1.c +++ b/Modem/protocol/mp1.c @@ -3,9 +3,6 @@ #include #include -static int okC; // FIXME: remove -static int erC; - static void mp1Decode(MP1 *mp1) { // This decode function is basic and bare minimum. // It does nothing more than extract the data @@ -42,17 +39,13 @@ void mp1Poll(MP1 *mp1) { // frame length, which means the flag signifies // the end of the packet. Pass control to the // decoder. - // kprintf("Got checksum: %d.\n", mp1->buffer[mp1->packetLength-1]); if ((mp1->checksum_in & 0xff) == 0x00) { - //kprintf("Correct checksum. Found %d.\n", mp1->buffer[mp1->packetLength-1]); - kprintf("[OK%d] ", okC++); mp1Decode(mp1); } else { - // Checksum was incorrect - kprintf("[ER%d] ", erC++); - mp1Decode(mp1); - //kprintf("Incorrect checksum. Found %d, ", mp1->buffer[mp1->packetLength]); - //kprintf("should be %d\n", mp1->checksum_in); + // Checksum was incorrect, we don't do anything, + // but you can enable the decode anyway, if you + // need it for testing or debugging + // mp1Decode(mp1); } } // If the above is not the case, this must be the @@ -60,7 +53,6 @@ void mp1Poll(MP1 *mp1) { mp1->reading = true; mp1->packetLength = 0; mp1->checksum_in = MP1_CHECKSUM_INIT; - //kprintf("Checksum init with %d\n", mp1->checksum_in); // We have indicated that we are reading, // and reset the length counter. Now we'll @@ -91,7 +83,6 @@ void mp1Poll(MP1 *mp1) { // still less than our max length, put the incoming // byte in the buffer. if (!mp1->escape) mp1->checksum_in = mp1->checksum_in ^ byte; - //kprintf("Checksum is now %d\n", mp1->checksum_in); mp1->buffer[mp1->packetLength++] = byte; } else { // If not, we have a problem: The buffer has overrun @@ -130,7 +121,6 @@ void mp1Send(MP1 *mp1, const void *_buffer, size_t length) { // Initialize checksum mp1->checksum_out = MP1_CHECKSUM_INIT; - //kprintf("Checksum init with %d\n", mp1->checksum_out); // Transmit the HDLC_FLAG to signify start of TX kfile_putc(HDLC_FLAG, mp1->modem); @@ -140,12 +130,10 @@ void mp1Send(MP1 *mp1, const void *_buffer, size_t length) { // output function while (length--) { mp1->checksum_out = mp1->checksum_out ^ *buffer; - //kprintf("Checksum is now %d\n", mp1->checksum_out); mp1Putbyte(mp1, *buffer++); } // Write checksum to end of packet - kprintf("Sending packet with checksum %d\n", mp1->checksum_out); mp1Putbyte(mp1, mp1->checksum_out); // Transmit a HDLC_FLAG to signify end of TX diff --git a/buildrev.h b/buildrev.h index bf98b44..c0a0ade 100644 --- a/buildrev.h +++ b/buildrev.h @@ -1,2 +1,2 @@ -#define VERS_BUILD 480 +#define VERS_BUILD 529 #define VERS_HOST "vixen"