Indentation mess cleanup
This commit is contained in:
parent
c7ff5cc5f1
commit
80459cbbd3
226
Modem/hardware.c
226
Modem/hardware.c
|
@ -3,12 +3,12 @@
|
||||||
//////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////
|
||||||
|
|
||||||
#include "hardware.h" // We need the header for this code
|
#include "hardware.h" // We need the header for this code
|
||||||
#include "afsk.h" // We also need to know about the AFSK modem
|
#include "afsk.h" // We also need to know about the AFSK modem
|
||||||
|
|
||||||
#include <cpu/irq.h> // Interrupt functions from BertOS
|
#include <cpu/irq.h> // Interrupt functions from BertOS
|
||||||
|
|
||||||
#include <avr/io.h> // AVR IO functions from BertOS
|
#include <avr/io.h> // AVR IO functions from BertOS
|
||||||
#include <avr/interrupt.h> // AVR interrupt functions from BertOS
|
#include <avr/interrupt.h> // AVR interrupt functions from BertOS
|
||||||
|
|
||||||
// A reference to our modem "object"
|
// A reference to our modem "object"
|
||||||
static Afsk *modem;
|
static Afsk *modem;
|
||||||
|
@ -25,80 +25,80 @@ static Afsk *modem;
|
||||||
// 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)
|
||||||
{
|
{
|
||||||
// Store a reference to our modem "object"
|
// Store a reference to our modem "object"
|
||||||
modem = _modem;
|
modem = _modem;
|
||||||
|
|
||||||
// Also make sure that we are not trying to use
|
// Also make sure that we are not trying to use
|
||||||
// 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 a timer to control how often our sampling functions
|
// We need a timer to control how often our sampling functions
|
||||||
// should run. To do this we will need to change some registers.
|
// should run. To do this we will need to change some registers.
|
||||||
// First we do some configuration on the Timer/Counter Control
|
// First we do some configuration on the Timer/Counter Control
|
||||||
// Register 1, aka Timer1.
|
// Register 1, aka Timer1.
|
||||||
//
|
//
|
||||||
// The following bits are set:
|
// The following bits are set:
|
||||||
// CS10: ClockSource 10, sets no prescaler on the clock,
|
// CS10: ClockSource 10, sets no prescaler on the clock,
|
||||||
// meaning it will run at the same speed as the CPU, ie 16MHz
|
// meaning it will run at the same speed as the CPU, ie 16MHz
|
||||||
// WGM13 and WGM12 together enables "Timer Mode 12", which
|
// 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).
|
||||||
// TOP means that we specify a maximum value for the timer, and
|
// TOP means that we specify a maximum value for the timer, and
|
||||||
// once that value is reached, an interrupt will be triggered.
|
// once that value is reached, an interrupt will be triggered.
|
||||||
// The timer will then start from zero again. As just noted,
|
// The timer will then start from zero again. As just noted,
|
||||||
// the place we specify this value is in the ICR1 register.
|
// the place we specify this value is in the ICR1 register.
|
||||||
TCCR1A = 0;
|
TCCR1A = 0;
|
||||||
TCCR1B = BV(CS10) | BV(WGM13) | BV(WGM12);
|
TCCR1B = BV(CS10) | BV(WGM13) | BV(WGM12);
|
||||||
|
|
||||||
// We now set the ICR1 register to what count value we want to
|
// We now 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.
|
||||||
// Since the timer is running at 16MHz, the counter will be
|
// Since the timer is running at 16MHz, the counter will be
|
||||||
// incremented 16 million times each second, and we want the
|
// incremented 16 million times each second, and we want the
|
||||||
// interrupt to trigger 9600 times each second. The formula for
|
// interrupt to trigger 9600 times each second. The formula for
|
||||||
// calculating the value of ICR1 (the TOP value) is:
|
// calculating the value of ICR1 (the TOP value) is:
|
||||||
// (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. Note that we can also specify a clock
|
// 9.6KHz sampling rate. Note that we can also specify a clock
|
||||||
// correction to this calculation. If you measure your processors
|
// correction to this calculation. If you measure your processors
|
||||||
// actual clock speed to 16.095MHz, define FREQUENCY_CORRECTION
|
// actual clock speed to 16.095MHz, define FREQUENCY_CORRECTION
|
||||||
// as 9500, and the actual sampling (and this modulation and
|
// as 9500, and the actual sampling (and this modulation and
|
||||||
// demodulation) will be much closer to an actual 9600 Hz.
|
// demodulation) will be much closer to an actual 9600 Hz.
|
||||||
// No crystals are perfect though, and will also drift with
|
// No crystals are perfect though, and will also drift with
|
||||||
// temperature variations, but if you have a board with a
|
// temperature variations, but if you have a board with a
|
||||||
// crystal that is way off frequency, this can help alot.
|
// crystal that is way off frequency, this can help alot.
|
||||||
ICR1 = (((CPU_FREQ+FREQUENCY_CORRECTION)) / 9600) - 1;
|
ICR1 = (((CPU_FREQ+FREQUENCY_CORRECTION)) / 9600) - 1;
|
||||||
|
|
||||||
// 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
|
||||||
// the reference voltage to VCC (5V), and the next selects
|
// the reference voltage to VCC (5V), and the next selects
|
||||||
// the ADC channel (basically what pin we are capturing on)
|
// the ADC channel (basically what pin we are capturing on)
|
||||||
ADMUX = BV(REFS0) | ch;
|
ADMUX = BV(REFS0) | ch;
|
||||||
|
|
||||||
DDRC &= ~BV(ch); // Set the selected channel (pin) to input
|
DDRC &= ~BV(ch); // Set the selected channel (pin) to input
|
||||||
PORTC &= ~BV(ch); // Initialize the selected pin to LOW
|
PORTC &= ~BV(ch); // Initialize the selected pin to LOW
|
||||||
DIDR0 |= BV(ch); // Disable the Digital Input Buffer on selected pin
|
DIDR0 |= BV(ch); // Disable the Digital Input Buffer on selected pin
|
||||||
|
|
||||||
// Now a little more configuration to get the ADC working
|
// Now a little more configuration to get the ADC working
|
||||||
// the way we want
|
// the way we want
|
||||||
ADCSRB = BV(ADTS2) | // Setting these three on (1-1-1) sets the ADC to
|
ADCSRB = BV(ADTS2) | // Setting these three on (1-1-1) sets the ADC to
|
||||||
BV(ADTS1) | // "Timer1 capture event". That means we can declare
|
BV(ADTS1) | // "Timer1 capture event". That means we can declare
|
||||||
BV(ADTS0); // an ISR in the ADC Vector, that will then get called
|
BV(ADTS0); // an ISR in the ADC Vector, that will then get called
|
||||||
// everytime the ADC has a sample ready, which will
|
// everytime the ADC has a sample ready, which will
|
||||||
// happen at the 9.6Khz sampling rate we set up earlier
|
// happen at the 9.6Khz sampling rate we set up earlier
|
||||||
|
|
||||||
ADCSRA = BV(ADEN) | // ADC Enable - Yes, we need to turn it on :)
|
ADCSRA = BV(ADEN) | // ADC Enable - Yes, we need to turn it on :)
|
||||||
BV(ADSC) | // ADC Start Converting - Tell it to start doing conversions
|
BV(ADSC) | // ADC Start Converting - Tell it to start doing conversions
|
||||||
BV(ADATE) | // Enable autotriggering - Enables the autotrigger on complete
|
BV(ADATE)| // Enable autotriggering - Enables the autotrigger on complete
|
||||||
BV(ADIE) | // ADC Interrupt enable - Enables an interrupt to be called
|
BV(ADIE) | // ADC Interrupt enable - Enables an interrupt to be called
|
||||||
BV(ADPS2); // Enable prescaler flag 2 (1-0-0 = division by 16 = 1MHz)
|
BV(ADPS2); // Enable prescaler flag 2 (1-0-0 = division by 16 = 1MHz)
|
||||||
// This sets the ADC to run at 1MHz. This is out of spec,
|
// This sets the ADC to run at 1MHz. This is out of spec,
|
||||||
// Since it's normal operating range is only up to 200KHz.
|
// Since it's normal operating range is only up to 200KHz.
|
||||||
// But don't worry, it's not dangerous! I promise it wont
|
// But don't worry, it's not dangerous! I promise it wont
|
||||||
// blow up :) There is a downside to running at this speed
|
// blow up :) There is a downside to running at this speed
|
||||||
// though, hence the "out of spec", which is that we get
|
// though, hence the "out of spec", which is that we get
|
||||||
// a much lower resolution on the output. In this case,
|
// a much lower resolution on the output. In this case,
|
||||||
// it's not a problem though, since we don't need the full
|
// it's not a problem though, since we don't need the full
|
||||||
// 10-bit resolution, so we'll take fast and less precise!
|
// 10-bit resolution, so we'll take fast and less precise!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -114,52 +114,52 @@ void hw_afsk_adcInit(int ch, Afsk *_modem)
|
||||||
bool hw_ptt_on;
|
bool hw_ptt_on;
|
||||||
bool hw_afsk_dac_isr;
|
bool hw_afsk_dac_isr;
|
||||||
DECLARE_ISR(ADC_vect) {
|
DECLARE_ISR(ADC_vect) {
|
||||||
TIFR1 = BV(ICF1);
|
TIFR1 = BV(ICF1);
|
||||||
|
|
||||||
// Call the routine for analysing the captured sample
|
// Call the routine for analysing the captured sample
|
||||||
// Notice that we read the ADC sample, and then bitshift
|
// Notice that we read the ADC sample, and then bitshift
|
||||||
// by two places to the right, effectively eliminating
|
// by two places to the right, effectively eliminating
|
||||||
// two bits of precision. But we didn't have those
|
// two bits of precision. But we didn't have those
|
||||||
// anyway, because the ADC is running at high speed.
|
// anyway, because the ADC is running at high speed.
|
||||||
// We then subtract 128 from the value, to get the
|
// We then subtract 128 from the value, to get the
|
||||||
// representation to match an AC waveform. We need to
|
// representation to match an AC waveform. We need to
|
||||||
// do this because the AC waveform (from the audio input)
|
// do this because the AC waveform (from the audio input)
|
||||||
// is biased by +2.5V, which is nessecary, since the ADC
|
// is biased by +2.5V, which is nessecary, since the ADC
|
||||||
// can't read negative voltages. By doing this simple
|
// can't read negative voltages. By doing this simple
|
||||||
// math, we bring it back to an AC representation
|
// math, we bring it back to an AC representation
|
||||||
// we can do further calculations on.
|
// we can do further calculations on.
|
||||||
afsk_adc_isr(modem, ((int16_t)((ADC) >> 2) - 128));
|
afsk_adc_isr(modem, ((int16_t)((ADC) >> 2) - 128));
|
||||||
|
|
||||||
// We also need to check if we're supposed to spit
|
// We also need to check if we're supposed to spit
|
||||||
// out some modulated data to the DAC.
|
// out some modulated data to the DAC.
|
||||||
if (hw_afsk_dac_isr) {
|
if (hw_afsk_dac_isr) {
|
||||||
// If there is, it's easy to actually do so. We
|
// If there is, it's easy to actually do so. We
|
||||||
// calculate what the sample should be in the
|
// calculate what the sample should be in the
|
||||||
// DAC ISR, and apply the bitmask 11110000. This
|
// DAC ISR, and apply the bitmask 11110000. This
|
||||||
// simoultaneously spits out our 4-bit digital
|
// simoultaneously spits out our 4-bit digital
|
||||||
// sample to the four pins connected to our DAC
|
// sample to the four pins connected to our DAC
|
||||||
// circuit, which then converts it to an analog
|
// circuit, which then converts it to an analog
|
||||||
// waveform. The reason for the " | BV(3)" is that
|
// waveform. The reason for the " | BV(3)" is that
|
||||||
// we also need to trigger another pin controlled
|
// we also need to trigger another pin controlled
|
||||||
// by the PORTD register. This is the PTT pin
|
// by the PORTD register. This is the PTT pin
|
||||||
// which tells the radio to open it transmitter.
|
// which tells the radio to open it transmitter.
|
||||||
PORTD = (afsk_dac_isr(modem) & 0xF0) | BV(3);
|
PORTD = (afsk_dac_isr(modem) & 0xF0) | BV(3);
|
||||||
} else {
|
} else {
|
||||||
// If we're not supposed to transmit anything, we
|
// If we're not supposed to transmit anything, we
|
||||||
// keep quiet by continously sending 128, which
|
// keep quiet by continously sending 128, which
|
||||||
// when converted to an AC waveform by the DAC,
|
// when converted to an AC waveform by the DAC,
|
||||||
// equates to a steady, unchanging 0 volts.
|
// equates to a steady, unchanging 0 volts.
|
||||||
if (hw_ptt_on) {
|
if (hw_ptt_on) {
|
||||||
PORTD = 136;
|
PORTD = 136;
|
||||||
} else {
|
} else {
|
||||||
PORTD = 128;
|
PORTD = 128;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// * "finally" is probably the wrong description here.
|
// (*) "finally" is probably the wrong description here.
|
||||||
// "All the f'ing time" is probably more accurate :)
|
// "All the f'ing time" is probably more accurate :)
|
||||||
// but it felt like it was a long way down here,
|
// but it felt like it was a long way down here,
|
||||||
// writing all the explanations. I think this is a
|
// writing all the explanations. I think this is a
|
||||||
|
|
|
@ -5,9 +5,9 @@
|
||||||
#ifndef FSK_MODEM_HW
|
#ifndef FSK_MODEM_HW
|
||||||
#define FSK_MODEM_HW
|
#define FSK_MODEM_HW
|
||||||
|
|
||||||
#include "cfg/cfg_arch.h" // Architecture configuration
|
#include "cfg/cfg_arch.h" // Architecture configuration
|
||||||
|
|
||||||
#include <avr/io.h> // AVR IO functions from BertOS
|
#include <avr/io.h> // AVR IO functions from BertOS
|
||||||
|
|
||||||
//////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////
|
||||||
// Definitions and some useful macros //
|
// Definitions and some useful macros //
|
||||||
|
|
282
Modem/main.c
282
Modem/main.c
|
@ -3,40 +3,40 @@
|
||||||
// First things first, all the includes we need //
|
// First things first, all the includes we need //
|
||||||
//////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////
|
||||||
|
|
||||||
#include <cpu/irq.h> // Interrupt functionality from BertOS
|
#include <cpu/irq.h> // Interrupt functionality from BertOS
|
||||||
|
|
||||||
#include <drv/ser.h> // Serial driver from BertOS
|
#include <drv/ser.h> // Serial driver from BertOS
|
||||||
#include <drv/timer.h> // Timer driver from BertOS
|
#include <drv/timer.h> // Timer driver from BertOS
|
||||||
|
|
||||||
#include <stdio.h> // Standard input/output
|
#include <stdio.h> // Standard input/output
|
||||||
#include <string.h> // String operations
|
#include <string.h> // String operations
|
||||||
|
|
||||||
#include "afsk.h" // Header for AFSK modem
|
#include "afsk.h" // Header for AFSK modem
|
||||||
#include "protocol/mp1.h" // Header for MP.1 protocol
|
#include "protocol/mp1.h" // Header for MP.1 protocol
|
||||||
|
|
||||||
#if SERIAL_DEBUG
|
#if SERIAL_DEBUG
|
||||||
#include "cfg/debug.h" // Debug configuration from BertOS
|
#include "cfg/debug.h" // Debug configuration from BertOS
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////
|
||||||
// A few definitions //
|
// A few definitions //
|
||||||
//////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////
|
||||||
|
|
||||||
static Afsk afsk; // Declare a AFSK modem struct
|
static Afsk afsk; // Declare a AFSK modem struct
|
||||||
static MP1 mp1; // Declare a protocol struct
|
static MP1 mp1; // Declare a protocol struct
|
||||||
static Serial ser; // Declare a serial interface struct
|
static Serial ser; // Declare a serial interface struct
|
||||||
|
|
||||||
#define ADC_CH 0 // Define which channel (pin) we want
|
#define ADC_CH 0 // Define which channel (pin) we want
|
||||||
// for the ADC (this is A0 on arduino)
|
// for the ADC (this is A0 on arduino)
|
||||||
|
|
||||||
|
|
||||||
static uint8_t serialBuffer[MP1_MAX_DATA_SIZE]; // This is a buffer for incoming serial data
|
static uint8_t serialBuffer[MP1_MAX_DATA_SIZE]; // This is a buffer for incoming serial data
|
||||||
|
|
||||||
static int sbyte; // For holding byte read from serial port
|
static int sbyte; // For holding byte read from serial port
|
||||||
static size_t serialLen = 0; // Counter for counting length of data from serial
|
static size_t serialLen = 0; // Counter for counting length of data from serial
|
||||||
static bool sertx = false; // Flag signifying whether it's time to send data
|
static bool sertx = false; // Flag signifying whether it's time to send data
|
||||||
// Received on the serial port.
|
// received on the serial port.
|
||||||
#define SER_BUFFER_FULL (serialLen < MP1_MAX_DATA_SIZE-1)
|
#define SER_BUFFER_FULL (serialLen < MP1_MAX_DATA_SIZE-1)
|
||||||
|
|
||||||
//////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////
|
||||||
|
@ -47,147 +47,147 @@ 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) {
|
||||||
if (SERIAL_DEBUG) {
|
if (SERIAL_DEBUG) {
|
||||||
kfile_printf(&ser.fd, "%.*s\n", packet->dataLength, packet->data);
|
kfile_printf(&ser.fd, "%.*s\n", packet->dataLength, packet->data);
|
||||||
} else {
|
} else {
|
||||||
for (unsigned long i = 0; i < packet->dataLength; i++) {
|
for (unsigned long i = 0; i < packet->dataLength; i++) {
|
||||||
kfile_putc(packet->data[i], &ser.fd);
|
kfile_putc(packet->data[i], &ser.fd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Simple initialization function.
|
// Simple initialization function.
|
||||||
static void init(void)
|
static void init(void)
|
||||||
{
|
{
|
||||||
// Enable interrupts
|
// Enable interrupts
|
||||||
IRQ_ENABLE;
|
IRQ_ENABLE;
|
||||||
|
|
||||||
// Initialize hardware timers
|
// Initialize hardware timers
|
||||||
timer_init();
|
timer_init();
|
||||||
|
|
||||||
// Initialize serial comms on UART0,
|
// Initialize serial comms on UART0,
|
||||||
// which is the hardware serial on arduino
|
// which is the hardware serial on arduino
|
||||||
ser_init(&ser, SER_UART0);
|
ser_init(&ser, SER_UART0);
|
||||||
ser_setbaudrate(&ser, 9600);
|
ser_setbaudrate(&ser, 9600);
|
||||||
|
|
||||||
// For some reason BertOS sets the serial
|
// For some reason BertOS sets the serial
|
||||||
// to 7 bit characters by default. We set
|
// to 7 bit characters by default. We set
|
||||||
// it to 8 instead.
|
// it to 8 instead.
|
||||||
UCSR0C = _BV(UCSZ01) | _BV(UCSZ00);
|
UCSR0C = _BV(UCSZ01) | _BV(UCSZ00);
|
||||||
|
|
||||||
// Create a modem context
|
// Create a modem context
|
||||||
afsk_init(&afsk, ADC_CH);
|
afsk_init(&afsk, ADC_CH);
|
||||||
// ... and a protocol context with the modem
|
// ... and a protocol context with the modem
|
||||||
mp1Init(&mp1, &afsk.fd, mp1Callback);
|
mp1Init(&mp1, &afsk.fd, mp1Callback);
|
||||||
|
|
||||||
// That's all!
|
// That's all!
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(void)
|
int main(void)
|
||||||
{
|
{
|
||||||
// Start by running the main initialization
|
// Start by running the main initialization
|
||||||
init();
|
init();
|
||||||
// Record the current tick count for time-keeping
|
// Record the current tick count for time-keeping
|
||||||
ticks_t start = timer_clock();
|
ticks_t start = timer_clock();
|
||||||
#if MP1_USE_TX_QUEUE
|
#if MP1_USE_TX_QUEUE
|
||||||
ticks_t frameQueued = 0;
|
ticks_t frameQueued = 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Go into ye good ol' infinite loop
|
// Go into ye good ol' infinite loop
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
// First we instruct the protocol to check for
|
// First we instruct the protocol to check for
|
||||||
// incoming data
|
// incoming data
|
||||||
mp1Poll(&mp1);
|
mp1Poll(&mp1);
|
||||||
|
|
||||||
|
|
||||||
// If there was actually some data waiting for us
|
// If there was actually some data waiting for us
|
||||||
// there, let's se what it tastes like :)
|
// there, let's se what it tastes like :)
|
||||||
if (!sertx && ser_available(&ser)) {
|
if (!sertx && ser_available(&ser)) {
|
||||||
// We then read a byte from the serial port.
|
// We then read a byte from the serial port.
|
||||||
// Notice that we use "_nowait" since we can't
|
// Notice that we use "_nowait" since we can't
|
||||||
// have this blocking execution until a byte
|
// have this blocking execution until a byte
|
||||||
// comes in.
|
// comes in.
|
||||||
sbyte = ser_getchar_nowait(&ser);
|
sbyte = ser_getchar_nowait(&ser);
|
||||||
|
|
||||||
// If SERIAL_DEBUG is specified we'll handle
|
// If SERIAL_DEBUG is specified we'll handle
|
||||||
// serial data as direct human input and only
|
// serial data as direct human input and only
|
||||||
// transmit when we get a LF character
|
// transmit when we get a LF character
|
||||||
#if SERIAL_DEBUG
|
#if SERIAL_DEBUG
|
||||||
// If we have not yet surpassed the maximum frame length
|
// If we have not yet surpassed the maximum frame length
|
||||||
// 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_DATA_SIZE) && (sbyte != 10)) {
|
if ((serialLen < MP1_MAX_DATA_SIZE) && (sbyte != 10)) {
|
||||||
// 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
|
||||||
serialLen++;
|
serialLen++;
|
||||||
} else {
|
} else {
|
||||||
// If one of the above conditions were actually the
|
// If one of the above conditions were actually the
|
||||||
// case, it means we have to transmit, se we set
|
// case, it means we have to transmit, se we set
|
||||||
// transmission flag to true.
|
// transmission flag to true.
|
||||||
sertx = true;
|
sertx = true;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
// Otherwise we assume the modem is running
|
// Otherwise we assume the modem is running
|
||||||
// in automated mode, and we push out data
|
// in automated mode, and we push out data
|
||||||
// as it becomes available. We either transmit
|
// as it becomes available. We either transmit
|
||||||
// immediately when the max frame length has
|
// immediately when the max frame length has
|
||||||
// been reached, or when we get no input for
|
// been reached, or when we get no input for
|
||||||
// a certain amount of time.
|
// a certain amount of time.
|
||||||
|
|
||||||
if (serialLen < MP1_MAX_DATA_SIZE-1) {
|
if (serialLen < MP1_MAX_DATA_SIZE-1) {
|
||||||
// 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
|
||||||
serialLen++;
|
serialLen++;
|
||||||
} else {
|
} else {
|
||||||
// If max frame length has been reached
|
// If max frame length has been reached
|
||||||
// we need to transmit.
|
// we need to transmit.
|
||||||
serialBuffer[serialLen] = sbyte;
|
serialBuffer[serialLen] = sbyte;
|
||||||
serialLen++;
|
serialLen++;
|
||||||
sertx = true;
|
sertx = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
start = timer_clock();
|
start = timer_clock();
|
||||||
#endif
|
#endif
|
||||||
} else {
|
} else {
|
||||||
if (!SERIAL_DEBUG && serialLen > 0 && timer_clock() - start > ms_to_ticks(TX_MAXWAIT)) {
|
if (!SERIAL_DEBUG && serialLen > 0 && timer_clock() - start > ms_to_ticks(TX_MAXWAIT)) {
|
||||||
sertx = true;
|
sertx = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check whether we should send data in our serial buffer
|
// Check whether we should send data in our serial buffer
|
||||||
if (sertx) {
|
if (sertx) {
|
||||||
#if MP1_USE_TX_QUEUE
|
#if MP1_USE_TX_QUEUE
|
||||||
mp1QueueFrame(&mp1, serialBuffer, serialLen);
|
mp1QueueFrame(&mp1, serialBuffer, serialLen);
|
||||||
frameQueued = timer_clock();
|
frameQueued = timer_clock();
|
||||||
sertx = false;
|
sertx = false;
|
||||||
serialLen = 0;
|
serialLen = 0;
|
||||||
#else
|
#else
|
||||||
// Wait until incoming packets are done
|
// Wait until incoming packets are done
|
||||||
if (!mp1CarrierSense(&mp1)) {
|
if (!mp1CarrierSense(&mp1)) {
|
||||||
// And then send the data
|
// And then send the data
|
||||||
mp1Send(&mp1, serialBuffer, serialLen);
|
mp1Send(&mp1, serialBuffer, serialLen);
|
||||||
|
|
||||||
// Reset the transmission flag and length counter
|
// Reset the transmission flag and length counter
|
||||||
sertx = false;
|
sertx = false;
|
||||||
serialLen = 0;
|
serialLen = 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#if MP1_USE_TX_QUEUE
|
#if MP1_USE_TX_QUEUE
|
||||||
// We first wait a little to see if more
|
// We first wait a little to see if more
|
||||||
// frames are coming in.
|
// frames are coming in.
|
||||||
if (timer_clock() - frameQueued > ms_to_ticks(MP1_QUEUE_TX_WAIT)) {
|
if (timer_clock() - frameQueued > ms_to_ticks(MP1_QUEUE_TX_WAIT)) {
|
||||||
if (!ser_available(&ser) && !mp1CarrierSense(&mp1)) {
|
if (!ser_available(&ser) && !mp1CarrierSense(&mp1)) {
|
||||||
// And if not, we send process the frame
|
// And if not, we send process the frame
|
||||||
// queue if possible.
|
// queue if possible.
|
||||||
mp1ProcessQueue(&mp1);
|
mp1ProcessQueue(&mp1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
1556
Modem/protocol/mp1.c
1556
Modem/protocol/mp1.c
File diff suppressed because it is too large
Load Diff
|
@ -7,23 +7,23 @@
|
||||||
// Options
|
// Options
|
||||||
#define MP1_ENABLE_TCP_COMPATIBILITY false
|
#define MP1_ENABLE_TCP_COMPATIBILITY false
|
||||||
#if MP1_ENABLE_TCP_COMPATIBILITY
|
#if MP1_ENABLE_TCP_COMPATIBILITY
|
||||||
#define MP1_ENABLE_COMPRESSION false
|
#define MP1_ENABLE_COMPRESSION false
|
||||||
#define MP1_ENABLE_CSMA true
|
#define MP1_ENABLE_CSMA true
|
||||||
#else
|
#else
|
||||||
#define MP1_ENABLE_COMPRESSION true
|
#define MP1_ENABLE_COMPRESSION true
|
||||||
#define MP1_ENABLE_CSMA false
|
#define MP1_ENABLE_CSMA false
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Frame sizing & checksum
|
// Frame sizing & checksum
|
||||||
#define MP1_INTERLEAVE_SIZE 12
|
#define MP1_INTERLEAVE_SIZE 12
|
||||||
#if MP1_ENABLE_COMPRESSION
|
#if MP1_ENABLE_COMPRESSION
|
||||||
#define MP1_MAX_FRAME_LENGTH 22 * MP1_INTERLEAVE_SIZE
|
#define MP1_MAX_FRAME_LENGTH 22 * MP1_INTERLEAVE_SIZE
|
||||||
#define MP1_USE_TX_QUEUE false
|
#define MP1_USE_TX_QUEUE false
|
||||||
#else
|
#else
|
||||||
#define MP1_MAX_FRAME_LENGTH 25 * MP1_INTERLEAVE_SIZE
|
#define MP1_MAX_FRAME_LENGTH 25 * MP1_INTERLEAVE_SIZE
|
||||||
#define MP1_USE_TX_QUEUE true
|
#define MP1_USE_TX_QUEUE true
|
||||||
#define MP1_TX_QUEUE_LENGTH 2
|
#define MP1_TX_QUEUE_LENGTH 2
|
||||||
#define MP1_QUEUE_TX_WAIT 16UL
|
#define MP1_QUEUE_TX_WAIT 16UL
|
||||||
#endif
|
#endif
|
||||||
#define MP1_HEADER_SIZE 1
|
#define MP1_HEADER_SIZE 1
|
||||||
#define MP1_CHECKSUM_SIZE 1
|
#define MP1_CHECKSUM_SIZE 1
|
||||||
|
@ -34,10 +34,10 @@
|
||||||
|
|
||||||
// These two parameters are used for
|
// These two parameters are used for
|
||||||
// P-persistent CSMA
|
// P-persistent CSMA
|
||||||
#define MP1_SETTLE_TIME 100UL // The minimum wait time before even considering sending
|
#define MP1_SETTLE_TIME 100UL // The minimum wait time before even considering sending
|
||||||
#define MP1_SLOT_TIME 100UL // The time to wait if deciding not to send
|
#define MP1_SLOT_TIME 100UL // The time to wait if deciding not to send
|
||||||
#define MP1_P_PERSISTENCE 85UL // The probability (between 0 and 255) for sending
|
#define MP1_P_PERSISTENCE 85UL // The probability (between 0 and 255) for sending
|
||||||
#define MP1_TXDELAY 0UL // Delay between turning on the transmitter and sending
|
#define MP1_TXDELAY 0UL // Delay between turning on the transmitter and sending
|
||||||
|
|
||||||
// We need to know some basic HDLC flag bytes
|
// We need to know some basic HDLC flag bytes
|
||||||
#define HDLC_FLAG 0x7E
|
#define HDLC_FLAG 0x7E
|
||||||
|
@ -48,9 +48,9 @@
|
||||||
// to send as padding if we need to pad a
|
// to send as padding if we need to pad a
|
||||||
// packet. Due to forward error correction,
|
// packet. Due to forward error correction,
|
||||||
// packets must have an even number of bytes.
|
// packets must have an even number of bytes.
|
||||||
#define MP1_PADDING 0x55
|
#define MP1_PADDING 0x55
|
||||||
#define MP1_HEADER_PADDED 0x01
|
#define MP1_HEADER_PADDED 0x01
|
||||||
#define MP1_HEADER_COMPRESSION 0x02
|
#define MP1_HEADER_COMPRESSION 0x02
|
||||||
|
|
||||||
// Just a forward declaration that this struct exists
|
// Just a forward declaration that this struct exists
|
||||||
struct MP1Packet;
|
struct MP1Packet;
|
||||||
|
@ -61,35 +61,35 @@ typedef void (*mp1_callback_t)(struct MP1Packet *packet);
|
||||||
|
|
||||||
// Struct for a protocol context
|
// Struct for a protocol context
|
||||||
typedef struct MP1 {
|
typedef struct MP1 {
|
||||||
uint8_t buffer[MP1_MAX_FRAME_LENGTH+MP1_INTERLEAVE_SIZE]; // A buffer for incoming packets
|
uint8_t buffer[MP1_MAX_FRAME_LENGTH+MP1_INTERLEAVE_SIZE]; // A buffer for incoming packets
|
||||||
KFile *modem; // KFile access to the modem
|
KFile *modem; // KFile access to the modem
|
||||||
size_t packetLength; // Counter for received packet length
|
size_t packetLength; // Counter for received packet length
|
||||||
size_t readLength; // This is the full read length, including parity bytes
|
size_t readLength; // This is the full read length, including parity bytes
|
||||||
uint8_t calculatedParity; // Calculated parity for incoming data block
|
uint8_t calculatedParity; // Calculated parity for incoming data block
|
||||||
mp1_callback_t callback; // The function to call when a packet has been received
|
mp1_callback_t callback; // The function to call when a packet has been received
|
||||||
uint8_t checksum_in; // Rolling checksum for incoming packets
|
uint8_t checksum_in; // Rolling checksum for incoming packets
|
||||||
uint8_t checksum_out; // Rolling checksum for outgoing packets
|
uint8_t checksum_out; // Rolling checksum for outgoing packets
|
||||||
bool reading; // True when we have seen a HDLC flag
|
bool reading; // True when we have seen a HDLC flag
|
||||||
bool escape; // We need to know if we are in an escape sequence
|
bool escape; // We need to know if we are in an escape sequence
|
||||||
ticks_t settleTimer; // Timer used for carrier sense settling
|
ticks_t settleTimer; // Timer used for carrier sense settling
|
||||||
long correctionsMade; // A counter for how many corrections were made to a packet
|
long correctionsMade; // A counter for how many corrections were made to a packet
|
||||||
uint8_t interleaveCounter; // Keeps track of when we have received an entire interleaved block
|
uint8_t interleaveCounter; // Keeps track of when we have received an entire interleaved block
|
||||||
uint8_t interleaveOut[MP1_INTERLEAVE_SIZE]; // A buffer for interleaving bytes before they are sent
|
uint8_t interleaveOut[MP1_INTERLEAVE_SIZE]; // A buffer for interleaving bytes before they are sent
|
||||||
uint8_t interleaveIn[MP1_INTERLEAVE_SIZE]; // A buffer for storing interleaved bytes before they are deinterleaved
|
uint8_t interleaveIn[MP1_INTERLEAVE_SIZE]; // A buffer for storing interleaved bytes before they are deinterleaved
|
||||||
uint8_t randomSeed; // A seed for the pseudo-random number generator
|
uint8_t randomSeed; // A seed for the pseudo-random number generator
|
||||||
#if MP1_USE_TX_QUEUE
|
#if MP1_USE_TX_QUEUE
|
||||||
bool queueProcessing; // For sending queued frames without preamble after first one
|
bool queueProcessing; // For sending queued frames without preamble after first one
|
||||||
size_t queueLength; // The length of the transmission queue
|
size_t queueLength; // The length of the transmission queue
|
||||||
size_t frameLengths[MP1_TX_QUEUE_LENGTH]; // The lengths of the frames in the queue
|
size_t frameLengths[MP1_TX_QUEUE_LENGTH]; // The lengths of the frames in the queue
|
||||||
uint8_t frameQueue[MP1_TX_QUEUE_LENGTH] // A buffer for a queued frame
|
uint8_t frameQueue[MP1_TX_QUEUE_LENGTH] // A buffer for a queued frame
|
||||||
[MP1_MAX_DATA_SIZE];
|
[MP1_MAX_DATA_SIZE];
|
||||||
#endif
|
#endif
|
||||||
} MP1;
|
} MP1;
|
||||||
|
|
||||||
// A struct encapsulating a network packet
|
// A struct encapsulating a network packet
|
||||||
typedef struct MP1Packet {
|
typedef struct MP1Packet {
|
||||||
const uint8_t *data; // Pointer to the actual data in the packet
|
const uint8_t *data; // Pointer to the actual data in the packet
|
||||||
size_t dataLength; // The length of the received data
|
size_t dataLength; // The length of the received data
|
||||||
} MP1Packet;
|
} MP1Packet;
|
||||||
|
|
||||||
// Declarations of functions
|
// Declarations of functions
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
#define VERS_BUILD 1756
|
#define VERS_BUILD 1758
|
||||||
#define VERS_HOST "shard"
|
#define VERS_HOST "shard"
|
||||||
|
|
Loading…
Reference in New Issue