Updated doc. Cleanup.

This commit is contained in:
Mark Qvist 2014-04-09 23:33:15 +02:00
parent 65820627ec
commit 5452a7f662
6 changed files with 74 additions and 67 deletions

View File

@ -6,8 +6,7 @@
#include "config.h" // This stores basic configuration #include "config.h" // This stores basic configuration
#include "hardware.h" // Hardware functions are nice to have too :) #include "hardware.h" // Hardware functions are nice to have too :)
#include <drv/timer.h> // Timer driver from BertOS #include <drv/timer.h> // Timer driver from BertOS
//FIXME: is this needed ? #include <cfg/module.h>
#include <cpu/power.h> // Power management from BertOS #include <cpu/power.h> // Power management from BertOS
#include <cpu/pgm.h> // Access to PROGMEM from BertOS #include <cpu/pgm.h> // 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. // bits in a stream and returns true if they differ.
#define TRANSITION_FOUND(bits) BITS_DIFFER((bits), (bits) >> 1) #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 // Phase sync constants
#define PHASE_BITS 8 #define PHASE_BITS 8 // How much to increment phase counter each sample
#define PHASE_INC 1 // FIXME: originally 1 #define PHASE_INC 1 // Nudge by an eigth of a sample each adjustment
#define PHASE_MAX (SAMPLESPERBIT * PHASE_BITS) #define PHASE_MAX (SAMPLESPERBIT * PHASE_BITS) // Resolution of our phase counter = 64
#define PHASE_THRESHOLD (PHASE_MAX / 4) // FIXME: originally /2 #define PHASE_THRESHOLD (PHASE_MAX / 4) // Target transition point of our phase window
// Modulation constants // 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 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)) #define SPACE_INC (uint16_t)(DIV_ROUND(SIN_LEN * (uint32_t)SPACE_FREQ, CONFIG_AFSK_DAC_SAMPLERATE))
// HDLC flag bytes // HDLC flag bytes
@ -111,7 +124,6 @@ STATIC_ASSERT(!(CONFIG_AFSK_DAC_SAMPLERATE % BITRATE));
// Link Layer Control and Demodulation // // Link Layer Control and Demodulation //
////////////////////////////////////////////////////// //////////////////////////////////////////////////////
static int adjustCount; // FIXME: Debug
// hdlcParse ///////////////////////////////////////// // hdlcParse /////////////////////////////////////////
// This function looks at the raw bits demodulated from // This function looks at the raw bits demodulated from
// the physical medium and tries to parse actual data // 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. // false and stopping the here.
ret = false; ret = false;
hdlc->receiving = false; hdlc->receiving = false;
kprintf("RX overrun 1!"); // FIXME: remove these
LED_RX_OFF(); LED_RX_OFF();
} }
@ -169,8 +180,6 @@ static bool hdlcParse(Hdlc *hdlc, bool bit, FIFOBuffer *fifo) {
// of the received bytes. // of the received bytes.
hdlc->currentByte = 0; hdlc->currentByte = 0;
hdlc->bitIndex = 0; hdlc->bitIndex = 0;
//if (adjustCount > 25) kprintf("[AC%d]", adjustCount); // this slows down stuff and makes it work. wtf?!
adjustCount = 0;
return ret; return ret;
} }
@ -242,7 +251,6 @@ static bool hdlcParse(Hdlc *hdlc, bool bit, FIFOBuffer *fifo) {
// If it is, abort and return false // If it is, abort and return false
hdlc->receiving = false; hdlc->receiving = false;
LED_RX_OFF(); LED_RX_OFF();
kprintf("RX overrun 3!");
ret = false; ret = false;
} }
} }
@ -255,7 +263,6 @@ static bool hdlcParse(Hdlc *hdlc, bool bit, FIFOBuffer *fifo) {
// If it is, well, you know by now! // If it is, well, you know by now!
hdlc->receiving = false; hdlc->receiving = false;
LED_RX_OFF(); LED_RX_OFF();
kprintf("RX overrun 4!");
ret = false; 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 // it's center at the bit transitions. Thus, we synchronise
// our timing to the transmitter, even if it's timing is // our timing to the transmitter, even if it's timing is
// a little off compared to our own. // a little off compared to our own.
if (TRANSITION_FOUND(afsk->sampledBits)) { if (SIGNAL_TRANSITIONED(afsk->sampledBits)) {
adjustCount++;
if (afsk->currentPhase < PHASE_THRESHOLD) { if (afsk->currentPhase < PHASE_THRESHOLD) {
afsk->currentPhase += PHASE_INC; afsk->currentPhase += PHASE_INC;
} else { } else {
@ -363,27 +369,29 @@ void afsk_adc_isr(Afsk *afsk, int8_t currentSample) {
afsk->actualBits <<= 1; afsk->actualBits <<= 1;
// We determine the actual bit value by reading // 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 // more 1's, we will assume that the transmitter
// sent us a one, otherwise we assume a zero // sent us a one, otherwise we assume a zero
// FIXME: Increasing this to 5 bit determine uint8_t bits = afsk->sampledBits & 0x0f;
uint8_t bits = afsk->sampledBits & 0x07; uint8_t c = 0;
if (bits == 0x07 || // 111 c += bits & BV(1);
bits == 0x06 || // 110 c += bits & BV(2);
bits == 0x05 || // 101 c += bits & BV(3);
bits == 0x03 // 011 c += bits & BV(4);
) { c += bits & BV(5);
afsk->actualBits |= 1; if (c >= 3) afsk->actualBits |= 1;
}
// uint8_t bits = afsk->sampledBits & 0x0f; //// Alternative using only three bits //////////
// uint8_t c = 0; // uint8_t bits = afsk->sampledBits & 0x07;
// c += bits & BV(1); // if (bits == 0x07 || // 111
// c += bits & BV(2); // bits == 0x06 || // 110
// c += bits & BV(3); // bits == 0x05 || // 101
// c += bits & BV(4); // bits == 0x03 // 011
// c += bits & BV(5); // ) {
// if (c >= 3) afsk->actualBits |= 1; // afsk->actualBits |= 1;
// }
/////////////////////////////////////////////////
// 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 NRZ coding, so if 2 consecutive bits // 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 #define BIT_STUFF_LEN 5
// A macro for switching what tone is being // 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) #define SWITCH_TONE(inc) (((inc) == MARK_INC) ? SPACE_INC : MARK_INC)
// This function starts the transmission // This function starts the transmission
static void afsk_txStart(Afsk *afsk) { static void afsk_txStart(Afsk *afsk) {
if (!afsk->sending) { if (!afsk->sending) {
// Initialize the phase increment to // Initialize the phase increment to
// that of the mark frequency // that of the mark frequency (zero)
afsk->phaseInc = MARK_INC; afsk->phaseInc = MARK_INC;
// Reset the phase accumulator to 0 // Reset the phase accumulator to 0
afsk->phaseAcc = 0; afsk->phaseAcc = 0;

View File

@ -11,7 +11,7 @@
#define CONFIG_AFSK_RXTIMEOUT 0 // How long a read operation from the modem #define CONFIG_AFSK_RXTIMEOUT 0 // How long a read operation from the modem
// will wait for data before timing out. // 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 #define CONFIG_AFSK_TRAILER_LEN 100UL // The length of the packet tail in milliseconds
#endif #endif

View File

@ -17,6 +17,10 @@ static Afsk *modem;
// And now for the actual hardware functions // // And now for the actual hardware functions //
////////////////////////////////////////////////////// //////////////////////////////////////////////////////
// M1 correction = 9500
// M2 correction = 40000
#define FREQUENCY_CORRECTION 0
// This function initializes the ADC and configures // This function initializes the ADC and configures
// it the way we need. // it the way we need.
void hw_afsk_adcInit(int ch, Afsk *_modem) 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 // a pin that can't be used for analog input
ASSERT(ch <= 5); ASSERT(ch <= 5);
// We need to do some configuration on the Timer/Counter Control // We need a timer to control how often our sampling functions
// Register 1, aka Timer1 // 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: // The following bits are set:
// CS11: ClockSource 11, sets the prescaler to 8, ie 2MHz // CS10: ClockSource 10, sets no prescaler on the clock,
// WGM13 and WGM12 together enables Timer Mode 12, which // 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 // is Clear Timer on Compare, compare set to TOP, and the
// source for the TOP value is ICR1 (Input Capture Register1). // source for the TOP value is ICR1 (Input Capture Register1).
TCCR1A = 0; 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 // Then we set the ICR1 register to what count value we want to
// reset (and thus trigger the interrupt) at. // reset (and thus trigger the interrupt) at.
@ -47,7 +55,8 @@ void hw_afsk_adcInit(int ch, Afsk *_modem)
// (CPUClock / Prescaler) / desired frequency - 1 // (CPUClock / Prescaler) / desired frequency - 1
// So that's what well put in this register to set up our // So that's what well put in this register to set up our
// 9.6KHz sampling rate. // 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 reference to AVCC (5V), select pin
// Set the ADMUX register. The first part (BV(REFS0)) sets // Set the ADMUX register. The first part (BV(REFS0)) sets

View File

@ -29,7 +29,8 @@ static Serial ser; // Declare a serial interface struct
#define TEST_TX false // Whether we should send test packets #define TEST_TX false // Whether we should send test packets
// periodically, plus what to send: // 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 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. // so we can process each packet as they are decoded.
// Right now it just prints the packet to the serial port. // Right now it just prints the packet to the serial port.
static void mp1Callback(struct MP1Packet *packet) { static void mp1Callback(struct MP1Packet *packet) {
//kfile_printf(&ser.fd, "%.*s\r\n", packet->dataLength, packet->data); kfile_printf(&ser.fd, "%.*s\n", packet->dataLength, packet->data);
kprintf("%.*s\n", packet->dataLength, packet->data); //kprintf("%.*s\n", packet->dataLength, packet->data);
} }
// Simple initialization function. // Simple initialization function.
@ -57,8 +58,7 @@ static void init(void)
// Enable interrupts // Enable interrupts
IRQ_ENABLE; IRQ_ENABLE;
// Initialize BertOS debug bridge // Initialize BertOS debug bridge
kdbg_init(); // kdbg_init();
kprintf("Init\n");
// Initialize hardware timers // Initialize hardware timers
timer_init(); timer_init();
@ -103,7 +103,6 @@ int main(void)
// and the byte is not a "transmit" (newline) character, // and the byte is not a "transmit" (newline) character,
// we should store it for transmission. // we should store it for transmission.
if ((serialLen < MP1_MAX_FRAME_LENGTH) && (sbyte != 138)) { if ((serialLen < MP1_MAX_FRAME_LENGTH) && (sbyte != 138)) {
//kprintf("Byte: %d\n", sbyte); // FIXME: delete
// Put the read byte into the buffer; // Put the read byte into the buffer;
serialBuffer[serialLen] = sbyte; serialBuffer[serialLen] = sbyte;
// Increment the read length counter // Increment the read length counter
@ -127,7 +126,7 @@ int main(void)
} }
// Periodically send test data if we should do so // 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; // Reset the timer counter;
start = timer_clock(); start = timer_clock();
// And send a test packet! // And send a test packet!

View File

@ -3,9 +3,6 @@
#include <string.h> #include <string.h>
#include <drv/ser.h> #include <drv/ser.h>
static int okC; // FIXME: remove
static int erC;
static void mp1Decode(MP1 *mp1) { static void mp1Decode(MP1 *mp1) {
// This decode function is basic and bare minimum. // This decode function is basic and bare minimum.
// It does nothing more than extract the data // It does nothing more than extract the data
@ -42,17 +39,13 @@ void mp1Poll(MP1 *mp1) {
// frame length, which means the flag signifies // frame length, which means the flag signifies
// the end of the packet. Pass control to the // the end of the packet. Pass control to the
// decoder. // decoder.
// kprintf("Got checksum: %d.\n", mp1->buffer[mp1->packetLength-1]);
if ((mp1->checksum_in & 0xff) == 0x00) { if ((mp1->checksum_in & 0xff) == 0x00) {
//kprintf("Correct checksum. Found %d.\n", mp1->buffer[mp1->packetLength-1]);
kprintf("[OK%d] ", okC++);
mp1Decode(mp1); mp1Decode(mp1);
} else { } else {
// Checksum was incorrect // Checksum was incorrect, we don't do anything,
kprintf("[ER%d] ", erC++); // but you can enable the decode anyway, if you
mp1Decode(mp1); // need it for testing or debugging
//kprintf("Incorrect checksum. Found %d, ", mp1->buffer[mp1->packetLength]); // mp1Decode(mp1);
//kprintf("should be %d\n", mp1->checksum_in);
} }
} }
// If the above is not the case, this must be the // If the above is not the case, this must be the
@ -60,7 +53,6 @@ void mp1Poll(MP1 *mp1) {
mp1->reading = true; mp1->reading = true;
mp1->packetLength = 0; mp1->packetLength = 0;
mp1->checksum_in = MP1_CHECKSUM_INIT; mp1->checksum_in = MP1_CHECKSUM_INIT;
//kprintf("Checksum init with %d\n", mp1->checksum_in);
// We have indicated that we are reading, // We have indicated that we are reading,
// and reset the length counter. Now we'll // 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 // still less than our max length, put the incoming
// byte in the buffer. // byte in the buffer.
if (!mp1->escape) mp1->checksum_in = mp1->checksum_in ^ byte; if (!mp1->escape) mp1->checksum_in = mp1->checksum_in ^ byte;
//kprintf("Checksum is now %d\n", mp1->checksum_in);
mp1->buffer[mp1->packetLength++] = byte; mp1->buffer[mp1->packetLength++] = byte;
} else { } else {
// If not, we have a problem: The buffer has overrun // 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 // Initialize checksum
mp1->checksum_out = MP1_CHECKSUM_INIT; mp1->checksum_out = MP1_CHECKSUM_INIT;
//kprintf("Checksum init with %d\n", mp1->checksum_out);
// Transmit the HDLC_FLAG to signify start of TX // Transmit the HDLC_FLAG to signify start of TX
kfile_putc(HDLC_FLAG, mp1->modem); kfile_putc(HDLC_FLAG, mp1->modem);
@ -140,12 +130,10 @@ void mp1Send(MP1 *mp1, const void *_buffer, size_t length) {
// output function // output function
while (length--) { while (length--) {
mp1->checksum_out = mp1->checksum_out ^ *buffer; mp1->checksum_out = mp1->checksum_out ^ *buffer;
//kprintf("Checksum is now %d\n", mp1->checksum_out);
mp1Putbyte(mp1, *buffer++); mp1Putbyte(mp1, *buffer++);
} }
// Write checksum to end of packet // Write checksum to end of packet
kprintf("Sending packet with checksum %d\n", mp1->checksum_out);
mp1Putbyte(mp1, mp1->checksum_out); mp1Putbyte(mp1, mp1->checksum_out);
// Transmit a HDLC_FLAG to signify end of TX // Transmit a HDLC_FLAG to signify end of TX

View File

@ -1,2 +1,2 @@
#define VERS_BUILD 480 #define VERS_BUILD 529
#define VERS_HOST "vixen" #define VERS_HOST "vixen"