Merge pull request #19 from OpenARDF/master

Pull changes on Main into Dev1 branch
Dev1
OpenARDF 2020-06-30 16:03:32 -04:00 zatwierdzone przez GitHub
commit ed8dfa5bbd
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 4AEE18F83AFDEB23
15 zmienionych plików z 375 dodań i 228 usunięć

Wyświetl plik

@ -32,8 +32,9 @@
#include "defs.h"
#include "linkbus.h"
#include "morse.h"
#include <avr/wdt.h>
#ifdef COMPILE_FOR_ATMELSTUDIO7
#if COMPILE_FOR_ATMELSTUDIO7
#include <avr/io.h>
#include <avr/eeprom.h>
#include <string.h>
@ -45,10 +46,6 @@
#include "ardooweeno.h"
#endif /* COMPILE_FOR_ATMELSTUDIO7 */
#ifdef USE_WATCHDOG
#include <avr/wdt.h>
#endif
#define MAX_PATTERN_TEXT_LENGTH 20
#define TEMP_STRING_LENGTH (MAX_PATTERN_TEXT_LENGTH + 10)
@ -75,8 +72,11 @@ volatile int g_startclock_interval = 60;
volatile BOOL g_audio_tone_on = FALSE;
volatile uint8_t g_lastSeconds = 0x00;
volatile int16_t g_sync_pin_timer = 0;
volatile BOOL g_sync_pin_stable = FALSE;
volatile BOOL g_sync_enabled = TRUE;
#ifndef COMPILE_FOR_ATMELSTUDIO7
#if !COMPILE_FOR_ATMELSTUDIO7
FoxType& operator++ (FoxType & orig)
{
orig = static_cast < FoxType > (orig + 1); /* static_cast required because enum + int -> int */
@ -98,6 +98,28 @@ volatile uint8_t g_lastSeconds = 0x00;
{
return( a = static_cast < FoxType > (a + b));
}
FoxType& operator-- (FoxType & orig)
{
orig = static_cast < FoxType > (orig - 1); /* static_cast required because enum - int -> int */
if(orig < BEACON)
{
orig = BEACON;
}
return( orig);
}
FoxType operator-- (FoxType & orig, int)
{
FoxType rVal = orig;
--orig;
return(rVal);
}
FoxType& operator -= (FoxType & a, int b)
{
return( a = static_cast < FoxType > (a - b));
}
#endif /* COMPILE_FOR_ATMELSTUDIO7 */
@ -117,7 +139,6 @@ static uint16_t EEMEM ee_ID_time;
static uint16_t EEMEM ee_clock_calibration;
static uint8_t EEMEM ee_override_DIP_switches;
static uint8_t EEMEM ee_enable_LEDs;
static uint8_t EEMEM ee_enable_sync;
static int16_t EEMEM ee_temp_calibration;
static uint8_t EEMEM ee_enable_start_timer;
@ -130,13 +151,10 @@ static volatile uint16_t g_clock_calibration = EEPROM_CLOCK_CALIBRATION_DEFAULT;
static volatile int16_t g_temp_calibration = EEPROM_TEMP_CALIBRATION_DEFAULT;
static volatile uint8_t g_override_DIP_switches = EEPROM_OVERRIDE_DIP_SW_DEFAULT;
static volatile uint8_t g_enable_LEDs;
static volatile uint8_t g_enable_sync;
static volatile uint8_t g_enable_start_timer;
static char g_tempStr[TEMP_STRING_LENGTH] = { '\0' };
static volatile uint8_t g_start_override = FALSE;
/*
* Function Prototypes
*/
@ -149,12 +167,9 @@ void setUpTemp(void);
void sendMorseTone(BOOL onOff);
void playStartingTone(uint8_t toneFreq);
void wdt_init(WDReset resetType);
void doSynchronization(void);
#ifndef USE_WATCHDOG
void (* resetFunc)(void) = 0; /*declare reset function @ address 0 */
#endif
#ifdef COMPILE_FOR_ATMELSTUDIO7
#if COMPILE_FOR_ATMELSTUDIO7
void loop(void);
int main(void)
#else
@ -163,7 +178,7 @@ void wdt_init(WDReset resetType);
{
while(initializeEEPROMVars())
{
; /* Initialize variables stored in EEPROM */
; /* Initialize variables stored in EEPROM */
}
setUpTemp();
@ -171,35 +186,40 @@ void wdt_init(WDReset resetType);
cli(); /*stop interrupts for setup */
/* set pins as outputs */
pinMode(PIN_NANO_LED, OUTPUT); /* The nano amber LED: This led blinks when off cycle and blinks with code when on cycle. */
digitalWrite(PIN_NANO_LED, OFF);
pinMode(PIN_NANO_KEY, OUTPUT); /* This pin is used to control the KEY line to the transmittter only active on cycle. */
digitalWrite(PIN_NANO_KEY, OFF);
pinMode(PIN_LED, OUTPUT); /* The nano amber LED: This led blinks when off cycle and blinks with code when on cycle. */
digitalWrite(PIN_LED, OFF);
pinMode(PIN_MORSE_KEY, OUTPUT); /* This pin is used to control the KEY line to the transmittter only active on cycle. */
digitalWrite(PIN_MORSE_KEY, OFF);
pinMode(PIN_AUDIO_OUT, OUTPUT);
digitalWrite(PIN_AUDIO_OUT, OFF);
/* set the pins that are inputs */
pinMode(PIN_NANO_SYNC, INPUT); /* This pin is used as the sync line
* NOTE: The original albq PIC controllers used the CPU reset line as the
* sync line. We had issues with transmitters getting out of sync during transport.
* later investigation found that ESD events during transport was resetting the
* PIC. This code will read this I/O line for sync and after finding that the I/O line
* has switched to the high state it never reads it again until a power cycle.
* The Arduino reset line does not go off board. ESD event caused out of sync issue fixed. */
pinMode(PIN_NANO_DIP_0, INPUT); /* fox switch LSB */
pinMode(PIN_NANO_DIP_1, INPUT); /* fox switch middle bit */
pinMode(PIN_NANO_DIP_2, INPUT); /* fox switch MSB */
pinMode(PIN_SYNC, INPUT_PULLUP); /* Sync button */
pinMode(PIN_DIP_0, INPUT_PULLUP); /* DIP switch LSB */
pinMode(PIN_DIP_1, INPUT_PULLUP); /* DIP switch middle bit */
pinMode(PIN_DIP_2, INPUT_PULLUP); /* DIP switch MSB */
digitalWrite(PIN_LED, OFF); /* Turn off led sync switch is now open */
digitalWrite(PIN_NANO_LED, OFF); /* Turn off led sync switch is now open */
/* Set unused pins as outputs pulled high */
pinMode(PIN_UNUSED_7, INPUT_PULLUP);
pinMode(PIN_UNUSED_8, INPUT_PULLUP);
pinMode(PIN_UNUSED_10, INPUT_PULLUP);
pinMode(PIN_UNUSED_12, INPUT_PULLUP);
pinMode(A0, INPUT_PULLUP);
pinMode(A1, INPUT_PULLUP);
pinMode(A2, INPUT_PULLUP);
pinMode(A3, INPUT_PULLUP);
#if !CAL_SIGNAL_ON_PD3
pinMode(PIN_CAL_OUT, INPUT_PULLUP);
#endif
/* set timer1 interrupt at 1Hz */
TCCR1A = 0; /* set entire TCCR1A register to 0 */
TCCR1B = 0; /* same for TCCR1B */
TCNT1 = 0; /*initialize counter value to 0 */
/* set timer1 interrupt at 1Hz */
TCCR1A = 0; /* set entire TCCR1A register to 0 */
TCCR1B = 0; /* same for TCCR1B */
TCNT1 = 0; /*initialize counter value to 0 */
/* Set compare match register for 1hz increments
************************************************************
** USE THIS TO FIX BOARD PROCESSOR CLOCK ERROR
** USE THIS TO CALIBRATE FOR BOARD PROCESSOR CLOCK ERROR
************************************************************/
/* first testing found bad drift relative to a gps stable clock (iphone timer) is was 10 seconds in about 50 minutes
* Today I measured the Arduino nano 16 Mhz clock and it was 16.050 MHz. Yes 50 Khz high!!
@ -222,8 +242,14 @@ void wdt_init(WDReset resetType);
TCCR2A = 0;
TCCR2B = 0;
TCCR2A |= (1 << WGM21); /* set Clear Timer on Compare Match (CTC) mode with OCR2A setting the top */
#if CAL_SIGNAL_ON_PD3
pinMode(PIN_CAL_OUT, OUTPUT); /* 601Hz Calibration Signal */
TCCR2A |= (1 << COM2A0); /* Toggle OC2A (PB3) on compare match */
#endif /* CAL_SIGNAL_ON_PD3 */
TCCR2B |= (1 << CS22) | (1 << CS21) | (1 << CS20); /* 1024 Prescaler */
OCR2A = 0x0C; /* set frequency to ~300 Hz (0x0c) */
OCR2B = 0x00;
/* Use system clock for Timer/Counter2 */
ASSR &= ~(1 << AS2);
/* Reset Timer/Counter2 Interrupt Mask Register */
@ -233,17 +259,22 @@ void wdt_init(WDReset resetType);
/* Timer 0 is for audio Start tone generation and control
* Note: Do not use millis() or DELAY() after TIMER0 has been reconfigured here! */
TCCR0A = 0x00;
/* TCCR0A |= (1 << COM0A0) | (1 << WGM01); / * Set toggle OC0A, CTC mode * / */
TCCR0A |= (1 << WGM01); /* Set CTC mode */
TCCR0A |= (1 << WGM01); /* Set CTC mode */
TCCR0B = 0x00;
TCCR0B |= (1 << CS02); /* Prescale 256 */
TCCR0B |= (1 << CS02); /* Prescale 256 */
OCR0A = DEFAULT_TONE_FREQUENCY;
TIMSK0 = 0x00;
TIMSK0 |= (1 << OCIE0A);
sei(); /*allow interrupts. Arm and run */
/* Sync button pin change interrupt */
PCMSK2 = 0x00;
PCMSK2 = (1 << PCINT19); /* Enable PCINT19 */
PCICR = 0x00;
PCICR = (1 << PCIE2); /* Enable pin change interrupt 2 */
linkbus_init(BAUD); /* Start the Link Bus serial comms */
sei(); /*allow interrupts. Arm and run */
linkbus_init(BAUD); /* Start the Link Bus serial comms */
lb_send_string((char*)"\n\nStored Data:\n", TRUE);
sprintf(g_tempStr, " ID: %s\n", g_messages_text[STATION_ID]);
@ -254,63 +285,43 @@ void wdt_init(WDReset resetType);
lb_send_string(g_tempStr, TRUE);
sprintf(g_tempStr, " LED: %s\n", g_enable_LEDs ? "ON" : "OFF");
lb_send_string(g_tempStr, TRUE);
sprintf(g_tempStr, " SYN: %s\n", g_enable_sync ? "ON" : "OFF");
lb_send_string(g_tempStr, TRUE);
sprintf(g_tempStr, " STA: %s\n", g_enable_start_timer ? "ON" : "OFF");
lb_send_string(g_tempStr, TRUE);
lb_send_NewPrompt();
if(g_override_DIP_switches)
{
g_fox = (FoxType)g_override_DIP_switches;
g_fox = CLAMP(BEACON, (FoxType)g_override_DIP_switches, INVALID_FOX);
if(g_fox == INVALID_FOX)
{
g_fox = BEACON;
}
}
else /* Read DIP Switches */
else /* Read DIP Switches */
{
if(digitalRead(PIN_NANO_DIP_0) == HIGH ) /*Lsb */
if(digitalRead(PIN_DIP_0) == LOW) /*Lsb */
{
g_fox++;
}
if(digitalRead(PIN_NANO_DIP_1) == HIGH ) /* middle bit */
if(digitalRead(PIN_DIP_1) == LOW) /* middle bit */
{
g_fox += 2;
}
if(digitalRead(PIN_NANO_DIP_2) == HIGH ) /* MSB */
if(digitalRead(PIN_DIP_2) == LOW) /* MSB */
{
g_fox += 4;
}
}
/*
* we now look at the sync line and then reset the time counters
* when the sync switch is released.
* */
if(g_enable_sync && (g_enable_start_timer || ((g_fox != FOXORING) && (g_fox != BEACON) && (g_fox != FOX_DEMO) && (g_fox != SPRINT_DEMO) && (g_fox != SPECTATOR))))
{
lb_send_string((char*)"Waiting for sync.\n", TRUE);
lb_send_string((char*)"Type \"GO\"\n", TRUE);
lb_send_NewPrompt();
while(( digitalRead(PIN_NANO_SYNC) == LOW) && !g_start_override)
{
if(g_enable_LEDs)
{
digitalWrite(PIN_NANO_LED, HIGH); /* arduino nano LED turn on led to show sync switch is closed */
}
handleLinkBusMsgs();
}
}
else
{
lb_send_string((char*)"Tx is running!\n", TRUE);
lb_send_NewPrompt();
}
TCNT1 = 0; /* Initialize 1-second counter value to 0 */
g_seconds_since_sync = 0;
g_fox_seconds_into_interval = 0;
g_start_override = TRUE;
#if !HARDWARE_EXTERNAL_DIP_PULLUPS_INSTALLED
/* Disable pull-ups to save power */
pinMode(PIN_DIP_0, INPUT); /* fox switch LSB */
pinMode(PIN_DIP_1, INPUT); /* fox switch middle bit */
pinMode(PIN_DIP_2, INPUT); /* fox switch MSB */
pinMode(PIN_DIP_0, OUTPUT);
pinMode(PIN_DIP_1, OUTPUT);
pinMode(PIN_DIP_2, OUTPUT);
#endif /* HARDWARE_EXTERNAL_DIP_PULLUPS_INSTALLED */
if((g_fox == BEACON) || (g_fox == SPECTATOR))
{
@ -341,7 +352,7 @@ void wdt_init(WDReset resetType);
wdt_init(WD_HW_RESETS);
#ifdef COMPILE_FOR_ATMELSTUDIO7
#if COMPILE_FOR_ATMELSTUDIO7
while(1)
{
loop();
@ -394,31 +405,24 @@ void __attribute__((optimize("O1"))) wdt_init(WDReset resetType)
/***********************************************************************
* Watchdog Timeout ISR
* Pin Change Interrupt 2 ISR
*
* Handles SYNC pin operation
*
* The Watchdog timer helps prevent lockups due to hardware problems.
* It is especially helpful in this application for preventing I2C bus
* errors from locking up the foreground process.
************************************************************************/
ISR(WDT_vect)
ISR(PCINT2_vect)
{
static uint8_t limit = 10;
BOOL pinVal = digitalRead(3);
/* g_i2c_not_timed_out = FALSE; / * unstick I2C * / */
/* Don't allow an unlimited number of WD interrupts to occur without enabling
* hardware resets. But a limited number might be required during hardware
* initialization. */
/* if(!g_enableHardwareWDResets && limit)
* {
* WDTCSR |= (1 << WDIE); / * this prevents hardware resets from occurring * /
* } */
if(limit)
if(pinVal) /* Sync is high */
{
limit--;
/* g_last_error_code = ERROR_CODE_WD_TIMEOUT; */
if(g_sync_pin_stable)
{
doSynchronization();
}
}
g_sync_pin_timer = 0;
}
@ -661,6 +665,7 @@ ISR(USART_UDRE_vect)
}
} /* End of UART Tx ISR */
/***********************************************************************
* Timer/Counter2 Compare Match B ISR
*
@ -677,6 +682,23 @@ ISR( TIMER2_COMPB_vect )
static BOOL playMorse = TRUE;
BOOL repeat = TRUE, finished = FALSE;
if(g_sync_enabled)
{
if(digitalRead(PIN_SYNC) == LOW)
{
if(g_sync_pin_timer < TIMER2_SECONDS_3)
{
g_sync_pin_timer++;
}
if(g_sync_pin_timer > TIMER2_SECONDS_1)
{
g_sync_pin_stable = TRUE;
digitalWrite(PIN_LED, HIGH);
}
}
}
if(blink_counter < -BLINK_LONG)
{
blink_count_direction = 1;
@ -781,10 +803,10 @@ ISR( TIMER2_COMPB_vect )
{
if(g_enable_LEDs)
{
digitalWrite(PIN_NANO_LED, HIGH); /* Nano LED */
digitalWrite(PIN_LED, HIGH); /* LED */
}
digitalWrite(PIN_NANO_KEY, HIGH); /* TX key line */
digitalWrite(PIN_MORSE_KEY, HIGH); /* TX key line */
}
if(playMorse)
@ -795,12 +817,12 @@ ISR( TIMER2_COMPB_vect )
}
else
{
if(g_enable_LEDs)
if(g_enable_LEDs && !g_sync_pin_stable)
{
digitalWrite(PIN_NANO_LED, key); /* nano LED */
digitalWrite(PIN_LED, key); /* LED */
}
digitalWrite(PIN_NANO_KEY, key); /* TX key line */
digitalWrite(PIN_MORSE_KEY, key); /* TX key line */
codeInc = g_code_throttle;
if(playMorse)
{
@ -813,8 +835,11 @@ ISR( TIMER2_COMPB_vect )
if(key)
{
key = OFF;
digitalWrite(PIN_NANO_LED, LOW); /* nano LED */
digitalWrite(PIN_NANO_KEY, LOW); /* TX key line */
if(!g_sync_pin_stable)
{
digitalWrite(PIN_LED, LOW); /* LED Off */
}
digitalWrite(PIN_MORSE_KEY, LOW); /* TX key line */
}
if(playMorse)
@ -836,10 +861,17 @@ ISR( TIMER2_COMPB_vect )
* modified from ISR example for microfox by Jerry Boyd WB8WFK
* this runs once a second and generates the cycle and sets control flags for the main controller.
*/
ISR(TIMER1_COMPA_vect) /*timer1 interrupt 1Hz */
ISR(TIMER1_COMPA_vect) /*timer1 interrupt 1Hz */
{
static int id_countdown = 0;
if(g_seconds_since_sync == 0) /* sync just occurred */
{
id_countdown = g_id_interval;
g_fox_counter = 1;
g_lastSeconds = 0;
}
g_seconds_since_sync++; /* Total elapsed time counter */
g_fox_seconds_into_interval++;
@ -855,6 +887,15 @@ ISR(TIMER1_COMPA_vect) /*timer1 interrupt 1Hz */
if(g_fox_counter > g_number_of_foxes)
{
g_fox_counter = 1;
if(g_sync_enabled)
{
PCMSK2 &= ~(1 << PCINT19); /* Disable PCINT19 */
PCICR &= ~(1 << PCIE2); /* Disable pin change interrupt 2 */
pinMode(PIN_SYNC, INPUT);
pinMode(PIN_SYNC, OUTPUT); /* Set sync pin as output low */
g_sync_enabled = FALSE;
}
}
g_fox_transition = TRUE;
g_fox_seconds_into_interval = 0;
@ -893,14 +934,10 @@ SIGNAL(TIMER0_COMPA_vect)
{
digitalWrite(PIN_AUDIO_OUT,OFF);
}
TCCR0A |= (1 << COM0A0);
}
else
{
TCCR0A = (1 << WGM01);
digitalWrite(PIN_AUDIO_OUT,OFF);
/* digitalWrite(6,OFF); */
}
}
@ -968,11 +1005,14 @@ void loop()
{
if(g_blinky_time)
{
digitalWrite(PIN_NANO_LED,OFF);
if(!g_sync_pin_stable)
{
digitalWrite(PIN_LED,OFF);
}
}
else
{
digitalWrite(PIN_NANO_LED,ON);
digitalWrite(PIN_LED,ON);
}
}
}
@ -1072,15 +1112,11 @@ void __attribute__((optimize("O0"))) handleLinkBusMsgs()
{
case MESSAGE_RESET:
{
#ifdef USE_WATCHDOG
wdt_init(WD_FORCE_RESET);
while(1)
{
;
}
#else
resetFunc(); /*call reset */
#endif /* USE_WATCHDOG */
wdt_init(WD_FORCE_RESET);
while(1)
{
;
}
}
break;
@ -1137,7 +1173,7 @@ void __attribute__((optimize("O0"))) handleLinkBusMsgs()
{
x = BEACON;
}
if(t == 'F')
else if(t == 'F')
{
if((u > '0') && (u < '6'))
{
@ -1170,7 +1206,7 @@ void __attribute__((optimize("O0"))) handleLinkBusMsgs()
}
}
if(x)
if(x != BEACON)
{
c = CLAMP(SPECTATOR,x,SPRINT_F5);
}
@ -1214,27 +1250,6 @@ void __attribute__((optimize("O0"))) handleLinkBusMsgs()
}
break;
case MESSAGE_SYNC_ENABLE:
{
if(lb_buff->fields[FIELD1][0])
{
if((lb_buff->fields[FIELD1][1] == 'F') || (lb_buff->fields[FIELD1][0] == '0'))
{
g_enable_sync = FALSE;
}
else
{
g_enable_sync = TRUE;
}
saveAllEEPROM();
}
sprintf(g_tempStr,"SYN:%s\n",g_enable_sync ? "ON" : "OFF");
lb_send_string(g_tempStr,FALSE);
}
break;
case MESSAGE_STARTTONES_ENABLE:
{
if(lb_buff->fields[FIELD1][0])
@ -1258,15 +1273,8 @@ void __attribute__((optimize("O0"))) handleLinkBusMsgs()
case MESSAGE_GO:
{
if(g_start_override)
{
lb_send_string((char*)"Already synced!\n",FALSE);
}
else
{
g_start_override = TRUE;
lb_send_string((char*)"Running!\n",FALSE);
}
doSynchronization();
lb_send_string((char*)"Re-sync successful!\n",FALSE);
}
break;
@ -1274,15 +1282,18 @@ void __attribute__((optimize("O0"))) handleLinkBusMsgs()
{
uint8_t flag = EEPROM_INITIALIZED_FLAG + 1;
eeprom_write_byte(&ee_interface_eeprom_initialization_flag,flag);
#ifdef USE_WATCHDOG
wdt_init(WD_FORCE_RESET);
while(1)
{
;
}
#else
resetFunc(); /*call reset */
#endif /* USE_WATCHDOG */
g_clock_calibration = 0xFFFF;
eeprom_update_word(&ee_clock_calibration,g_clock_calibration);
for(uint8_t i = 0; i < strlen(g_messages_text[STATION_ID]); i++)
{
eeprom_write_byte((uint8_t*)&ee_stationID_text,0xFF);
}
wdt_init(WD_FORCE_RESET);
while(1)
{
;
}
}
break;
@ -1411,7 +1422,7 @@ void __attribute__((optimize("O0"))) handleLinkBusMsgs()
}
float temp = 10. * getTemp();
sprintf(g_tempStr,"Temp: %d.%dC\n",(int)temp / 10,(int)temp % 10);
sprintf(g_tempStr,"Temp: %d.%dC\n",(int)temp / 10,abs((int)temp % 10));
lb_send_string(g_tempStr,FALSE);
}
break;
@ -1449,7 +1460,6 @@ BOOL initializeEEPROMVars()
g_temp_calibration = (int16_t)eeprom_read_word((uint16_t*)&ee_temp_calibration);
g_override_DIP_switches = eeprom_read_byte(&ee_override_DIP_switches);
g_enable_LEDs = eeprom_read_byte(&ee_enable_LEDs);
g_enable_sync = eeprom_read_byte(&ee_enable_sync);
g_enable_start_timer = eeprom_read_byte(&ee_enable_start_timer);
for(i = 0; i < 20; i++)
@ -1480,7 +1490,6 @@ BOOL initializeEEPROMVars()
g_temp_calibration = EEPROM_TEMP_CALIBRATION_DEFAULT;
g_override_DIP_switches = EEPROM_OVERRIDE_DIP_SW_DEFAULT;
g_enable_LEDs = EEPROM_ENABLE_LEDS_DEFAULT;
g_enable_sync = EEPROM_ENABLE_SYNC_DEFAULT;
g_enable_start_timer = EEPROM_ENABLE_STARTTIMER_DEFAULT;
strncpy(g_messages_text[STATION_ID],EEPROM_STATION_ID_DEFAULT,MAX_PATTERN_TEXT_LENGTH);
strncpy(g_messages_text[PATTERN_TEXT],EEPROM_PATTERN_TEXT_DEFAULT,MAX_PATTERN_TEXT_LENGTH);
@ -1510,7 +1519,6 @@ void saveAllEEPROM()
eeprom_update_word((uint16_t*)&ee_temp_calibration,(uint16_t)g_temp_calibration);
eeprom_update_byte(&ee_override_DIP_switches,g_override_DIP_switches);
eeprom_update_byte(&ee_enable_LEDs,g_enable_LEDs);
eeprom_update_byte(&ee_enable_sync,g_enable_sync);
eeprom_update_byte(&ee_enable_start_timer,g_enable_start_timer);
for(i = 0; i < strlen(g_messages_text[STATION_ID]); i++)
@ -1587,10 +1595,24 @@ uint16_t readADC()
*/
float getTemp(void)
{
float offset = (float)g_temp_calibration / 10.;
float offset = CLAMP(-200.,(float)g_temp_calibration / 10.,200.);
/* The offset (first term) was determined empirically */
readADC(); /* throw away first reading */
return(offset + (readADC() - 324.31) / 1.22);
}
void doSynchronization(void)
{
cli();
TCNT1 = 0; /* Initialize 1-second counter value to 0 */
g_seconds_since_sync = 0;
g_fox_seconds_into_interval = 0;
g_sync_pin_stable = FALSE;
digitalWrite(PIN_LED,LOW);
g_on_the_air = 0;
g_fox_counter = 1; /* Don't count on the 1-sec timer setting this in time */
sei();
}

Wyświetl plik

@ -26,9 +26,19 @@
#ifndef DEFS_H
#define DEFS_H
// #define COMPILE_FOR_ATMELSTUDIO7
#ifndef FALSE
#define FALSE 0
#endif
#ifdef COMPILE_FOR_ATMELSTUDIO7
#ifndef TRUE
#define TRUE !FALSE
#endif
#define COMPILE_FOR_ATMELSTUDIO7 FALSE
#define HARDWARE_EXTERNAL_DIP_PULLUPS_INSTALLED FALSE
#define CAL_SIGNAL_ON_PD3 FALSE
#if COMPILE_FOR_ATMELSTUDIO7
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
@ -52,12 +62,15 @@
#define OUTPUT 0x1
#endif
/* #define F_CPU 16000000UL / * gets declared in makefile * / */
#ifndef INPUT_PULLUP
#define INPUT_PULLUP 0x3
#endif
/* #define F_CPU 16000000UL / * gets declared in makefile * / */
/******************************************************
* Set the text that gets displayed to the user */
#define SW_REVISION "0.10"
#define SW_REVISION "0.16"
//#define TRANQUILIZE_WATCHDOG
@ -85,13 +98,19 @@ typedef unsigned char uint8_t;
#define null 0
#endif
#define PIN_NANO_LED 13
#define PIN_NANO_KEY 2
#define PIN_NANO_SYNC 3
#define PIN_NANO_DIP_0 4
#define PIN_NANO_DIP_1 5
#define PIN_NANO_DIP_2 6
#define PIN_MORSE_KEY 2
#define PIN_SYNC 3
#define PIN_DIP_0 4
#define PIN_DIP_1 5
#define PIN_DIP_2 6
#define PIN_UNUSED_7 7
#define PIN_UNUSED_8 8
#define PIN_AUDIO_OUT 9
#define PIN_UNUSED_10 10
#define PIN_CAL_OUT 11
#define PIN_UNUSED_12 12
#define PIN_LED 13
typedef enum {
BEACON = 0,
@ -120,8 +139,6 @@ INVALID_FOX
#define MAX_CODE_SPEED_WPM 20
#define MIN_CODE_SPEED_WPM 5
#define USE_WATCHDOG
typedef enum
{
WD_SW_RESETS,
@ -139,7 +156,7 @@ typedef enum
/******************************************************
* EEPROM definitions */
#define EEPROM_INITIALIZED_FLAG 0xB3
#define EEPROM_INITIALIZED_FLAG 0xB4
#define EEPROM_UNINITIALIZED 0x00
#define EEPROM_STATION_ID_DEFAULT "FOXBOX"
@ -158,33 +175,8 @@ typedef enum
#define EEPROM_TEMP_CALIBRATION_DEFAULT 147
#define EEPROM_OVERRIDE_DIP_SW_DEFAULT 0
#define EEPROM_ENABLE_LEDS_DEFAULT 1
#define EEPROM_ENABLE_SYNC_DEFAULT 1
#define EEPROM_ENABLE_STARTTIMER_DEFAULT 1
#define EEPROM_SI5351_CALIBRATION_DEFAULT 0x00
#define EEPROM_CLK0_OUT_DEFAULT 133000000
#define EEPROM_CLK1_OUT_DEFAULT 70000000
#define EEPROM_CLK2_OUT_DEFAULT 10700000
#define EEPROM_CLK0_ONOFF_DEFAULT OFF
#define EEPROM_CLK1_ONOFF_DEFAULT OFF
#define EEPROM_CLK2_ONOFF_DEFAULT OFF
#define EEPROM_BATTERY_EMPTY_MV 3430
/******************************************************
* General definitions for making the code easier to understand */
#define SDA_PIN (1 << PINC4)
#define SCL_PIN (1 << PINC5)
#define I2C_PINS (SCL_PIN | SDA_PIN)
#ifndef FALSE
#define FALSE 0
#endif
#ifndef TRUE
#define TRUE !FALSE
#endif
#ifndef BOOL
typedef uint8_t BOOL;
#endif
@ -197,10 +189,9 @@ typedef enum
#define UINT16_MAX __INT16_MAX__
#endif
#define ON 1
#define OFF 0
#define ON 1
#define TOGGLE 2
#define UNDETERMINED 3
#define MIN(A,B) ({ __typeof__(A) __a = (A); __typeof__(B) __b = (B); __a < __b ? __a : __b; })
@ -216,6 +207,7 @@ typedef enum
#define MAX_TIME 4294967295L
#define MAX_UINT16 65535
#define MAX_INT16 32767
#define MIN_INT16 -32768
/* Periodic TIMER2 interrupt timing definitions */
#define TIMER2_57HZ 10

Wyświetl plik

@ -28,7 +28,7 @@
#include "linkbus.h"
#include "defs.h"
#ifdef COMPILE_FOR_ATMELSTUDIO7
#if COMPILE_FOR_ATMELSTUDIO7
#include <string.h>
#include <stdio.h>
#endif /* COMPILE_FOR_ATMELSTUDIO7 */
@ -49,7 +49,6 @@ static const char textHelp[][23] = { "\nCommands:\n",
" RST - Reset\n",
" SPD - ID code speed\n",
" STA - Start tones\n",
" SYN - Sync on/off\n",
" TEM - Temperature\n",
" VER - S/W version\n" };

Wyświetl plik

@ -96,7 +96,6 @@ typedef enum
MESSAGE_FACTORY_RESET = 'F' * 100 + 'A' * 10 + 'C', /* Sets EEPROM back to defaults */
MESSAGE_OVERRIDE_DIP = 'D' * 100 + 'I' * 10 + 'P', /* Override DIP switch settings using this value */
MESSAGE_LEDS = 'L' * 100 + 'E' * 10 + 'D', /* Turn on or off LEDs - accepts 1 or 0 or ON or OFF */
MESSAGE_SYNC_ENABLE = 'S' * 100 + 'Y' * 10 + 'N', /* Enable or disable transmitter syncing */
MESSAGE_TEMP = 'T' * 100 + 'E' * 10 + 'M', /* Temperature data */
MESSAGE_SET_STATION_ID = 'I' * 10 + 'D', /* Sets amateur radio callsign text */
MESSAGE_GO = 'G' * 10 + 'O', /* Synchronizes clock */

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 2.9 MiB

Plik binarny nie jest wyświetlany.

Plik binarny nie jest wyświetlany.

Plik binarny nie jest wyświetlany.

Plik binarny nie jest wyświetlany.

Plik binarny nie jest wyświetlany.

Plik binarny nie jest wyświetlany.

Wyświetl plik

@ -0,0 +1,10 @@
files in this zip are:
1. readme.txt this file.
2. case_lid.stl the lid for the transmitter case.
3. bottom_half.stl the bottom main part of the case.
4. 80mbase.stl the sub chaassis that the PCB mounts on. Glue inside case.
5. audio_jack_holder.stl a bracket to hold optional audio jack for tone outputs.
6. 9vbattery_adaptor.stl a test adaptor for testbench testing with a powersupply.
All units are mm

Plik binarny nie jest wyświetlany.

157
README.md
Wyświetl plik

@ -1,22 +1,23 @@
<h1>WB8WFK ARDF Foxoring Transmitter</h1>
<p>This is a simple, inexpensive, transmitter controller for conducting ARDF Foxoring competitions and for demonstrating ARDF principles. The software project is an Arduino script that builds for and runs on most Arduino-like products, including <a href="https://www.adafruit.com/product/2590">AdaFruit's Metro Mini 328</a>, or <a href="https://www.sparkfun.com/products/11113">SparkFun's Arduino Pro Mini 328</a>, and many more.</p>
<p>This is a simple, inexpensive, transmitter and controller for conducting ARDF Foxoring competitions and for demonstrating ARDF principles. The software project is an Arduino script that builds for and runs on most Arduino-like products, including <a href="https://www.adafruit.com/product/2590">AdaFruit's Metro Mini 328</a>, or <a href="https://www.sparkfun.com/products/11113">SparkFun's Arduino Pro Mini 328</a>, and many more.</p>
<p>Controller support for all the common ARDF competition formats is provided: Classic, Sprint, and Foxoring.
<p>Controller support for all the common ARDF competition formats is provided: Classic, Sprint, and Foxoring.</p>
<h2>Software</h2>
<p>The software is a proper Arduino script that will open and build without warnings or errors in Arduino IDE version 1.8.12 and later. The Arduino IDE can also be used to program a device that holds a compatible bootloader. Most Arduino products ship with a bootloader pre-installed.</p>
<p>The software is a proper Arduino script that will open and build without warnings or errors in Arduino IDE version 1.8.12 and later. It has also been shown to work with the online <a href="https://create.arduino.cc/editor">Arduino Web Editor</a>. The Arduino IDE can be used to program a device that contains a compatible bootloader. Most Arduino products ship with a bootloader pre-installed.</p>
<p>After being programmed, the controller can be configured via a serial port on the board. An Arduino board that includes a USB-to-Serial converter will allow you to configure the controller with a simple USB cable (standard to micro) connected between a USB port on your computer to one on the Arduino board. Less sophisticated Arduino boards lacking a USB-to-Serial converter will require a special FTDI cable like <a href="https://www.adafruit.com/product/70">AdaFruit's FTDI Serial TTL-232 USB Cable</a>, or <a href="https://www.sparkfun.com/products/9718">SparkFun's FTDI Cable 5V</a>.</p>
<p>The controller includes an output pin for controlling a transmitter for sending Morse code characters (high = key down; low = key up) and a separate pin that sends the Morse code as audio tones that can be used to drive a speaker. The controller can also provide a sequence of starting-tones prompting competitors to begin a competition, and can thus serve as an electronic starting "gun" for use in ARDF events.</p>
<p>The fox-controller software provides an output pin for controlling a transmitter for sending Morse code characters (high = key down; low = key up) and a separate pin that sends the Morse code as audio tones that can be used to drive a speaker. The controller can also provide a sequence of starting-tones prompting competitors to begin a competition, and can thus serve as an electronic starting "gun" for use in ARDF events.</p>
<h3>Serial Commands</h3>
<p>The controller serial interface operates at 57600 baud that can be accessed using any serial TTY interface program such as PuTTY or Arduino's own Serial Monitor tool. It provides a command prompt > indicating that it is ready to receive recognized the following commands.<p>
<p>The fox-controller serial interface operates at 57600 baud, and can be accessed using any serial TTY interface program such as PuTTY or Arduino's own Serial Monitor tool. It provides a command prompt > indicating that it is ready to receive any of the following commands.
</p>
<pre><p><b>> CAL [num]</b> <= <i>* Sets the clock calibration for precise timing</i><br>
<b>> CAL</b> <= <i>Displays the clock calibration setting</i><br>
<b>> DIP [val]</b> <= <i>* Sets the competition format, overriding the DIP switch settings<br>
<b>> DIP</b> <= <i>Displays the competition format setting<br>
<b>> DIP [val]</b> <= <i>* Sets the competition format, overriding the DIP switch settings</i><br>
<b>> DIP</b> <= <i>Displays the competition format setting</i><br>
<b>> FAC</b> <= <i>Sets saved EEPROM values to their original defaults</i><br>
<b>> GO</b> <= <i>Starts operation from zero seconds, equivalent to pressing the sync button</i><br>
<b>> ID [string]</b> <= <i>* Sets the callsign that gets sent</i><br>
@ -24,23 +25,147 @@
<b>> LED [on|off]</b> <= <i>* Turns on/off LED pin</i><br>
<b>> LED</b> <= <i>Displays the LED pin setting</i><br>
<b>> RST</b> <= <i>Resets the processor</i><br>
<b>> SPD ID [num]</b> <= <i>* Sets the ID code speed in WPM<br>
<b>> SPD</b> <= <i>Displays the ID code speed setting<br>
<b>> SPD ID [num]</b> <= <i>* Sets the ID code speed in WPM</i><br>
<b>> SPD</b> <= <i>Displays the ID code speed setting</i><br>
<b>> STA [on|off]</b> <= <i>* Turns on/off the starting tones function</i><br>
<b>> STA</b> <= <i>Displays the starting tones setting</i><br>
<b>> SYN [on|off]</b> <= <i>* Turns on/off synchronization using sync button or "GO" command</i><br>
<b>> SYN</b> <= <i>Displays the synchronization setting</i><br>
<b>> TEM</b> <= <i>Displays the processor's temperature in C</i><br>
<b>> VER</b> <= <i>Displays the software version number</i><br></p></pre>
<p>* These values get stored to EEPROM and are retained between power cycles. </p>
<b>> VER</b> <= <i>Displays the software version number</i></p></pre>
<p>* These values get stored to EEPROM and are retained between power cycles. </p>
<h2>Hardware</h2>
<p>Look in the Hardware folder for all hardware-related documents</p>
<h3>Pinout</h3>
![Docs/ControllerPinout.png](Docs/ControllerPinout.png)
<pre><p><b>PB1 - Board Pin 9 (Output)</b> <= Audio Out (=Gnd when no tone)<br>
<b>PB5 - Board Pin 13 (Output)</b> <= LED On=+V<br>
<b>PD2 - Board Pin 2 (Output)</b> <= Key/PTT On=+V<br>
<b>PB5 - Board Pin 13 (Output)</b> <= LED On=VCC<br>
<b>PD2 - Board Pin 2 (Output)</b> <= Key/PTT On=VCC<br>
<b>PD3 - Board Pin 3 (Input)</b> <= Synchronize (mom. switch to Gnd)<br>
<b>PD4 - Board Pin 4 (Input)</b> <= DIP Switch Bit 0 (switch to Gnd)<br>
<b>PD5 - Board Pin 5 (Input)</b> <= DIP Switch Bit 1 (switch to Gnd)<br>
<b>PD6 - Board Pin 6 (Input)</b> <= DIP Switch Bit 2 (switch to Gnd)</p></pre>
<h2>Usage</h2>
<p>The transmitter can be configured using the serial port, or using the DIP switch and sync-button hardware interface. Only a subset of the possible configurations is available when using only the hardware interface. Configuring the DIP setting with a serial port command to anything but CLASSIC BEACON (zero) will disable the hardware DIP switch.</p>
<p>In the table below, default settings are shown in <b>boldface</b>. Serial command arguments may be abbreviated using the first letter of the word. For example: <b>> DIP CLASSIC BEACON</b> can be shortened to <b>> DIP C B</b>.</p>
<p>
<table>
<tr>
<th>Function</th>
<th>Software Commands</th>
<th>Hardware Settings</th>
</tr>
<tr>
<td>Homing Beacon</td>
<td><b>> DIP CLASSIC BEACON</b><br>[Note: the DIP switch must also be set to 0-0-0]</td>
<td>DIP = 0-0-0</td>
</tr>
<tr>
<td>Classic Fox#1</td>
<td>> DIP CLASSIC 1<br>> GO</td>
<td>DIP = 0-0-1<br>Sync to start</td>
</tr>
<tr>
<td>Classic Fox#2</td>
<td>> DIP CLASSIC 2<br>> GO</td>
<td>DIP = 0-1-0<br>Sync to start</td>
</tr>
<tr>
<td>Classic Fox#3</td>
<td>> DIP CLASSIC 3<br>> GO</td>
<td>DIP = 0-1-1<br>Sync to start</td>
</tr>
<tr>
<td>Classic Fox#4</td>
<td>> DIP CLASSIC 4<br>> GO</td>
<td>DIP = 1-0-0<br>Sync to start</td>
</tr>
<tr>
<td>Classic Fox#5</td>
<td>> DIP CLASSIC 5<br>> GO</td>
<td>DIP = 1-0-1<br>Sync to start</td>
</tr>
<tr>
<td>Classic Demonstration</td>
<td>> DIP CLASSIC DEMO</td>
<td>DIP = 1-1-0</td>
</tr>
<tr>
<td>Foxoring</td>
<td>> DIP FOXORING</td>
<td>DIP = 1-1-1</td>
</tr>
<tr>
<td>Spectator Beacon</td>
<td>> DIP FOXORING SPEC</td>
<td>N/A</td>
</tr>
<tr>
<td>Sprint Fox Slow #1</td>
<td>> DIP SPRINT S1</td>
<td>N/A</td>
</tr>
<tr>
<td>Sprint Fox Slow #2</td>
<td>> DIP SPRINT S2</td>
<td>N/A</td>
</tr>
<tr>
<td>Sprint Fox Slow #3</td>
<td>> DIP SPRINT S3</td>
<td>N/A</td>
</tr>
<tr>
<td>Sprint Fox Slow #4</td>
<td>> DIP SPRINT S4</td>
<td>N/A</td>
</tr>
<tr>
<td>Sprint Fox Slow #5</td>
<td>> DIP SPRINT S5</td>
<td>N/A</td>
</tr>
<tr>
<td>Sprint Fox Fast #1</td>
<td>> DIP SPRINT F1</td>
<td>N/A</td>
</tr>
<tr>
<td>Sprint Fox Fast #2</td>
<td>> DIP SPRINT F2</td>
<td>N/A</td>
</tr>
<tr>
<td>Sprint Fox Fast #3</td>
<td>> DIP SPRINT F3</td>
<td>N/A</td>
</tr>
<tr>
<td>Sprint Fox Fast #4</td>
<td>> DIP SPRINT F4</td>
<td>N/A</td>
</tr>
<tr>
<td>Sprint Fox Fast #5</td>
<td>> DIP SPRINT F5</td>
<td>N/A</td>
</tr>
<tr>
<td>Sprint Demonstration</td>
<td>> DIP SPRINT DEMO</td>
<td>N/A</td>
</tr>
<tr>
<td>Starting Tones Generator</td>
<td>> DIP [any of the above]<br><b>> STA ON</b><br>> GO</td>
<td>N/A</td>
</tr>
<tr>
<td>Synchronize</td>
<td>> GO</td>
<td>Pull sync pin low for at least 1 second<br>Allow sync pin to rise<br>[Must happen within 1 fox cycle after power-on]</td>
</tr>
</table>
</p>