mirror of
https://github.com/markqvist/OpenModem.git
synced 2024-12-29 01:16:17 -05:00
Updated doc. Cleanup.
This commit is contained in:
parent
65820627ec
commit
5452a7f662
83
Modem/afsk.c
83
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 <drv/timer.h> // Timer driver from BertOS
|
||||
//FIXME: is this needed ? #include <cfg/module.h>
|
||||
#include <drv/timer.h> // Timer driver from BertOS
|
||||
|
||||
#include <cpu/power.h> // Power management 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.
|
||||
#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;
|
||||
|
@ -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
|
@ -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
|
||||
|
13
Modem/main.c
13
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!
|
||||
|
@ -3,9 +3,6 @@
|
||||
#include <string.h>
|
||||
#include <drv/ser.h>
|
||||
|
||||
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
|
||||
|
@ -1,2 +1,2 @@
|
||||
#define VERS_BUILD 480
|
||||
#define VERS_BUILD 529
|
||||
#define VERS_HOST "vixen"
|
||||
|
Loading…
Reference in New Issue
Block a user