From 88cc9455f1f8a1c3e7d8a7698d5bf9431d05a25b Mon Sep 17 00:00:00 2001 From: Charles Date: Sun, 24 May 2020 16:48:50 -0400 Subject: [PATCH 1/6] Minor Changes o Added "VER" command for displaying version number. o Deletes and cleanup --- defs.h | 10 -------- linkbus.h | 7 ++---- vhf-allmode-microfox.ino | 54 +++++++++++++++++++++------------------- 3 files changed, 31 insertions(+), 40 deletions(-) diff --git a/defs.h b/defs.h index ec7a34e..eef1a5d 100644 --- a/defs.h +++ b/defs.h @@ -40,16 +40,6 @@ /*******************************************************/ -/****************************************************** - * Include only the necessary hardware support */ -// #define INCLUDE_SI5351_SUPPORT // Silicon Labs Programmable Clock -// #define INCLUDE_DS3231_SUPPORT // Maxim RTC -// #define INCLUDE_TRANSMITTER_SUPPORT -// #define INCLUDE_DAC081C085_SUPPORT -// #define ENABLE_PIN_CHANGE_INTERRUPT_0 -// #define ENABLE_PIN_CHANGE_INTERRUPT_1 -// #define ENABLE_PIN_CHANGE_INTERRUPT_2 - #ifndef uint16_t_defined #define uint16_t_defined typedef unsigned int uint16_t; diff --git a/linkbus.h b/linkbus.h index eafdd9b..d45b218 100644 --- a/linkbus.h +++ b/linkbus.h @@ -41,10 +41,8 @@ #define LINKBUS_MIN_TX_INTERVAL_MS 100 -//#define FOSC 8000000 /* Clock Speed */ #define FOSC 16000000 /* Clock Speed */ -#define BAUD 9600 -//#define BAUD 19200 +#define BAUD 57600 #define MYUBRR(b) (FOSC / 16 / (b) - 1) typedef enum @@ -112,13 +110,12 @@ typedef enum MESSAGE_SET_STATION_ID = 'I' * 10 + 'D', /* Sets amateur radio callsign text */ MESSAGE_SET_PATTERN = 'P' * 10 + 'A', /* Sets unique transmit pattern */ MESSAGE_CODE_SPEED = 'S' * 100 + 'P' * 10 + 'D', /* Sets id and pattern code speeds */ - MESSAGE_TIME_INTERVAL = 'T', /* Sets on-air, off-air, delay, and ID time intervals */ MESSAGE_ESP_COMM = 'E' * 100 + 'S' * 10 + 'P', /* Communications with ESP8266 controller */ MESSAGE_GO = 'G' * 10 + 'O', /* Start transmitting now without delay */ /* UTILITY MESSAGES */ MESSAGE_RESET = 'R' * 100 + 'S' * 10 + 'T', /* Processor reset */ - MESSAGE_WIFI = 'W' * 10 + 'I', /* Enable/disable WiFi */ + MESSAGE_VERSION = 'V' * 100 + 'E' * 10 + + 'R', /* S/W version number */ INVALID_MESSAGE = UINT16_MAX /* This value must never overlap a valid message ID */ } LBMessageID; diff --git a/vhf-allmode-microfox.ino b/vhf-allmode-microfox.ino index f02746a..f9c8a5d 100644 --- a/vhf-allmode-microfox.ino +++ b/vhf-allmode-microfox.ino @@ -60,13 +60,15 @@ void saveAllEEPROM(void); void transmitString(char msg[], int speed); void word_space(int speed); int codeBits(char alphaNum); -void (* resetFunc) (void) = 0; /*declare reset function @ address 0 */ + +#ifndef USE_WATCHDOG + void (* resetFunc) (void) = 0; /*declare reset function @ address 0 */ +#endif void setup() { initializeEEPROMVars(); /* Initialize variables stored in EEPROM */ - linkbus_init(57600); /* Start the Link Bus serial comms */ -/* Serial.begin(57600); // debug - this might not work with the Link Bus enabled or vice versa */ + linkbus_init(BAUD); /* Start the Link Bus serial comms */ linkbus_send_text((char*)"\n\nStored Data:\n"); sprintf(g_tempStr, " ID: %s\n", g_messages_text[STATION_ID]); linkbus_send_text(g_tempStr); @@ -76,13 +78,14 @@ void setup() linkbus_send_text(g_tempStr); sprintf(g_tempStr, " LED: %s\n", g_enable_LEDs == TRUE ? "ON" : "OFF"); linkbus_send_text(g_tempStr); -/* put your setup code here, to run once: - * set pins as outputs and inputs */ + + /* set pins as outputs */ pinMode(13, OUTPUT); /* The nano amber LED * This led blinks when off cycle and * blinks with code when on cycle. */ pinMode(2, OUTPUT); /* This pin is used to control the KEY line to the transmittter * only active on cycle. */ + /* set the pins that are inputs */ pinMode(3, INPUT); /* This pin is used as the sync line * NOTE: The original albq PIC controllers used the CPU reset line as the @@ -95,10 +98,6 @@ void setup() pinMode(5, INPUT); /* fox switch middle bit */ pinMode(6, INPUT); /* fox switch MSB */ - -/* set up interrupts and serial */ - - /* * read the dip switches and compute the desired fox number * */ @@ -589,7 +588,7 @@ void loop() /* * A R D F cycles MO and DEMO - * */ + */ while(1) /* Start of the standard ARDF and demo mode loop */ { /*get ready for first pass @@ -940,13 +939,14 @@ void __attribute__((optimize("O0"))) handleLinkBusMsgs() case MESSAGE_RESET: { #ifdef USE_WATCHDOG - wdt_init(WD_FORCE_RESET); - while(1) - { - ; - } -#endif /* USE_WATCHDOG */ - resetFunc(); /*call reset */ + wdt_init(WD_FORCE_RESET); + while(1) + { + ; + } +#else + resetFunc(); /*call reset */ +#endif // USE_WATCHDOG } break; @@ -1023,7 +1023,15 @@ 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 } break; @@ -1074,12 +1082,6 @@ void __attribute__((optimize("O0"))) handleLinkBusMsgs() } break; - case MESSAGE_TIME_INTERVAL: - { - /* Your code goes here */ - } - break; - case MESSAGE_SET_PATTERN: { if(lb_buff->fields[FIELD1][0]) @@ -1089,9 +1091,11 @@ void __attribute__((optimize("O0"))) handleLinkBusMsgs() } break; - case MESSAGE_BAND: + case MESSAGE_VERSION: { - /* Your code goes here */ + sprintf(g_tempStr, "SW Ver:%u\n", SW_REVISION); + linkbus_send_text(g_tempStr); + send_ack = FALSE; } break; From 74d837439dd6f90a94b8a321db527b20d056c312 Mon Sep 17 00:00:00 2001 From: DigitalConfections Date: Sun, 24 May 2020 19:57:00 -0400 Subject: [PATCH 2/6] Fix for previous commit o Deleted reference to MESSAGE_WIFI --- linkbus.cpp | 1 + vhf-allmode-microfox.ino | 7 ------- 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/linkbus.cpp b/linkbus.cpp index ee049f3..cbe647b 100644 --- a/linkbus.cpp +++ b/linkbus.cpp @@ -25,6 +25,7 @@ #include "linkbus.h" #include "defs.h" + //#include "util.h" //#include //#include diff --git a/vhf-allmode-microfox.ino b/vhf-allmode-microfox.ino index f9c8a5d..5c79cd4 100644 --- a/vhf-allmode-microfox.ino +++ b/vhf-allmode-microfox.ino @@ -930,12 +930,6 @@ void __attribute__((optimize("O0"))) handleLinkBusMsgs() switch(msg_id) { - case MESSAGE_WIFI: - { - /* Your code goes here */ - } - break; - case MESSAGE_RESET: { #ifdef USE_WATCHDOG @@ -1216,4 +1210,3 @@ void saveAllEEPROM() eeprom_update_byte((uint8_t*)&ee_pattern_text[i], 0); } - From 559b4a3a3f8a97b19f348fda1a4cb762f009e5ba Mon Sep 17 00:00:00 2001 From: Charles Date: Mon, 25 May 2020 10:07:29 -0400 Subject: [PATCH 3/6] TTY Terminal o Changed Linkbus to function more like a standard TTY terminal. o Cleaned up some unused defs --- defs.h | 82 ----------- linkbus.cpp | 44 ++++++ linkbus.h | 24 ++++ vhf-allmode-microfox.ino | 286 +++++++++++++++++++++++++++++---------- 4 files changed, 285 insertions(+), 151 deletions(-) diff --git a/defs.h b/defs.h index eef1a5d..654e61f 100644 --- a/defs.h +++ b/defs.h @@ -286,47 +286,6 @@ typedef enum /****************************************************** * UI Hardware-related definitions */ -typedef enum lcdRow -{ - ROW0, - ROW1, - NUMBER_OF_LCD_ROWS -} LcdRowType; - -typedef enum lcdColumn -{ - COL0, - COL1, - COL2, - COL3, - COL4, - COL5, - COL6, - COL7, - COL8, - COL9, - COL10, - COL11, - COL12, - COL13, - COL14, - COL15, - COL16, - COL17, - COL18, - COL19, - NUMBER_OF_LCD_COLS, - INVALID_LCD_COLUMN -} LcdColType; - -typedef enum -{ - BUTTON1_COLUMN = COL0, - BUTTON2_COLUMN = COL5, - BUTTON3_COLUMN = COL10, - BUTTON4_COLUMN = COL15 -} ButtonColumn; - typedef enum { FrequencyFormat, @@ -336,38 +295,6 @@ typedef enum #define DISPLAY_WIDTH_STRING_SIZE (NUMBER_OF_LCD_COLS + 1) -typedef uint8_t BackLightSettingType; -#define BL_OFF 0xFF -#define BL_LOW 0xCF -#define BL_MED 0x8F -#define BL_HIGH 0x00 - -typedef uint8_t ContrastType; - -typedef enum volumeSetting -{ - VOL_ZERO = 0, - VOL_10, - VOL_20, - VOL_30, - VOL_40, - VOL_50, - VOL_60, - VOL_70, - VOL_80, - VOL_90, - VOL_100, - DECREMENT_VOL, - INCREMENT_VOL, - VOL_NOT_SPECIFIED -} VolumeSetting; - -typedef enum volumeType -{ - TONE_VOLUME, - MAIN_VOLUME -} VolumeType; - typedef enum batteryType { BATTERY_9V, @@ -376,15 +303,6 @@ typedef enum batteryType BATTERY_UNKNOWN } BatteryType; -typedef enum buttons -{ - BUTTON1, - BUTTON2, - BUTTON3, - BUTTON4, - NUMBER_OF_BUTTONS -} ButtonType; - typedef enum { Minutes_Seconds, /* minutes up to 59 */ diff --git a/linkbus.cpp b/linkbus.cpp index cbe647b..b00c890 100644 --- a/linkbus.cpp +++ b/linkbus.cpp @@ -33,6 +33,9 @@ /* Global Variables */ static volatile BOOL g_bus_disabled = TRUE; +static const char crlf[] = "\n"; +static char lineTerm[8] = "\n"; +static const char textPrompt[] = "TX> "; static char g_tempMsgBuff[LINKBUS_MAX_MSG_LENGTH]; @@ -333,3 +336,44 @@ void lb_broadcast_num(uint16_t data, char* str) if(g_tempMsgBuff[0]) linkbus_send_text(g_tempMsgBuff); } + +/*********************************************************************************** + * Support for creating and sending various Terminal Mode Linkbus messages is provided below. + ************************************************************************************/ + +void lb_send_NewPrompt(void) +{ + linkbus_send_text((char*)crlf); +} + +void lb_send_NewLine(void) +{ + linkbus_send_text((char*)crlf); +} + +void linkbus_setLineTerm(char* term) +{ + sprintf(lineTerm, term); +} + +void lb_echo_char(uint8_t c) +{ + g_tempMsgBuff[0] = c; + g_tempMsgBuff[1] = '\0'; + linkbus_send_text(g_tempMsgBuff); +} + +BOOL lb_send_string(char* str) +{ + if(str == NULL) return TRUE; + if(strlen(str) > LINKBUS_MAX_MSG_LENGTH) return TRUE; + strncpy(g_tempMsgBuff, str, LINKBUS_MAX_MSG_LENGTH); + linkbus_send_text(g_tempMsgBuff); + return FALSE; +} + +void lb_send_value(uint16_t value, char* label) +{ + sprintf(g_tempMsgBuff, "> %s=%d%s", label, value, lineTerm); + linkbus_send_text(g_tempMsgBuff); +} diff --git a/linkbus.h b/linkbus.h index d45b218..dbf4e92 100644 --- a/linkbus.h +++ b/linkbus.h @@ -239,4 +239,28 @@ void lb_broadcast_num(uint16_t data, char* str); */ void lb_send_Help(void); +/** + */ +void lb_send_NewPrompt(void); + +/** + */ +void lb_send_NewLine(void); + +/** + */ +void linkbus_setLineTerm(char* term); + +/** + */ +void lb_echo_char(uint8_t c); + +/** + */ +BOOL lb_send_string(char* str); + +/** + */ +void lb_send_value(uint16_t value, char* label); + #endif /* LINKBUS_H_ */ diff --git a/vhf-allmode-microfox.ino b/vhf-allmode-microfox.ino index 5c79cd4..721ac51 100644 --- a/vhf-allmode-microfox.ino +++ b/vhf-allmode-microfox.ino @@ -237,6 +237,7 @@ void setup() ************************************************************************/ ISR(USART_RX_vect) { + static char textBuff[LINKBUS_MAX_MSG_FIELD_LENGTH]; static LinkbusRxBuffer* buff = NULL; static uint8_t charIndex = 0; static uint8_t field_index = 0; @@ -255,87 +256,234 @@ ISR(USART_RX_vect) if(buff) { rx_char = toupper(rx_char); - SMCR = 0x00; /* exit power-down mode */ - - if((rx_char == '$') || (rx_char == '!')) /* start of new message = $ */ - { - charIndex = 0; - buff->type = (rx_char == '!') ? LINKBUS_MSG_REPLY : LINKBUS_MSG_COMMAND; - field_len = 0; - msg_ID = LINKBUS_MSG_UNKNOWN; - receiving_msg = TRUE; - - /* Empty the field buffers */ - for(field_index = 0; field_index < LINKBUS_MAX_MSG_NUMBER_OF_FIELDS; field_index++) +// SMCR = 0x00; // exit power-down mode + +// if(g_terminal_mode) +// { + static uint8_t ignoreCount = 0; + + if(ignoreCount) { - buff->fields[field_index][0] = '\0'; + rx_char = '\0'; + ignoreCount--; + } + else if(rx_char == 0x1B) /* ESC sequence start */ + { + rx_char = '\0'; + + if(charIndex < LINKBUS_MAX_MSG_FIELD_LENGTH) + { + rx_char = textBuff[charIndex]; + } + + ignoreCount = 2; /* throw out the next two characters */ } - field_index = 0; - } - else if(receiving_msg) - { - if((rx_char == ',') || (rx_char == ';') || (rx_char == '?')) /* new field = ,; end of message = ; */ + if(rx_char == 0x0D) /* Handle carriage return */ { - /* if(field_index == 0) // message ID received */ - if(field_index > 0) + if(receiving_msg) { - buff->fields[field_index - 1][field_len] = 0; - } - - field_index++; - field_len = 0; - - if(rx_char == ';') - { - if(charIndex >= LINKBUS_MIN_MSG_LENGTH) + if(charIndex > 0) { - buff->id = (LBMessageID)msg_ID; - } - receiving_msg = FALSE; - } - else if(rx_char == '?') - { - buff->type = LINKBUS_MSG_QUERY; - if(charIndex > LINKBUS_MIN_MSG_LENGTH) - { - buff->id = (LBMessageID)msg_ID; - } - receiving_msg = FALSE; - } + buff->type = LINKBUS_MSG_QUERY; + buff->id = msg_ID; - if(!receiving_msg) - { - buff = 0; - } - } - else - { - if(field_index == 0) /* message ID received */ - { - msg_ID = msg_ID * 10 + rx_char; + if(field_index > 0) /* terminate the last field */ + { + buff->fields[field_index - 1][field_len] = 0; + } + + textBuff[charIndex] = '\0'; /* terminate last-message buffer */ + } + + lb_send_NewLine(); } else { - buff->fields[field_index - 1][field_len++] = rx_char; + buff->id = INVALID_MESSAGE; /* print help message */ + } + + charIndex = 0; + field_len = 0; + msg_ID = LINKBUS_MSG_UNKNOWN; + + field_index = 0; + buff = NULL; + + receiving_msg = FALSE; + } + else if(rx_char) + { + textBuff[charIndex] = rx_char; /* hold the characters for re-use */ + + if(charIndex) + { + if(rx_char == 0x7F) /* Handle backspace */ + { + charIndex--; + if(field_index == 0) + { + msg_ID -= textBuff[charIndex]; + msg_ID /= 10; + } + else if(field_len) + { + field_len--; + } + else + { + buff->fields[field_index][0] = '\0'; + field_index--; + } + } + else + { + if(rx_char == ' ') + { + if(textBuff[charIndex - 1] == ' ') + { + rx_char = '\0'; + } + else + { + /* if(field_index == 0) // message ID received */ + if(field_index > 0) + { + buff->fields[field_index - 1][field_len] = 0; + } + + field_index++; + field_len = 0; + } + } + else + { + if(field_index == 0) /* message ID received */ + { + msg_ID = msg_ID * 10 + rx_char; + } + else + { + buff->fields[field_index - 1][field_len++] = rx_char; + } + } + + charIndex = MIN(charIndex+1, LINKBUS_MAX_MSG_FIELD_LENGTH); + } + } + else + { + if((rx_char == 0x7F) || (rx_char == ' ')) /* Handle backspace and Space */ + { + rx_char = '\0'; + } + else /* start of new message */ + { + uint8_t i; + field_index = 0; + msg_ID = 0; + + msg_ID = msg_ID * 10 + rx_char; + + /* Empty the field buffers */ + for(i = 0; i < LINKBUS_MAX_MSG_NUMBER_OF_FIELDS; i++) + { + buff->fields[i][0] = '\0'; + } + + receiving_msg = TRUE; + charIndex = MIN(charIndex+1, LINKBUS_MAX_MSG_FIELD_LENGTH); + } + } + + if(rx_char) + { + lb_echo_char(rx_char); } } - } - else if(rx_char == 0x0D) /* Handle carriage return */ - { - buff->id = (LBMessageID)LINKBUS_MSG_UNKNOWN; - charIndex = LINKBUS_MAX_MSG_LENGTH; - field_len = 0; - msg_ID = LINKBUS_MSG_UNKNOWN; - field_index = 0; - buff = NULL; - } - - if(++charIndex >= LINKBUS_MAX_MSG_LENGTH) - { - receiving_msg = FALSE; - charIndex = 0; - } +// } +// else +// { +// if((rx_char == '$') || (rx_char == '!')) /* start of new message = $ */ +// { +// charIndex = 0; +// buff->type = (rx_char == '!') ? LINKBUS_MSG_REPLY : LINKBUS_MSG_COMMAND; +// field_len = 0; +// msg_ID = LINKBUS_MSG_UNKNOWN; +// receiving_msg = TRUE; +// +// /* Empty the field buffers */ +// for(field_index = 0; field_index < LINKBUS_MAX_MSG_NUMBER_OF_FIELDS; field_index++) +// { +// buff->fields[field_index][0] = '\0'; +// } +// +// field_index = 0; +// } +// else if(receiving_msg) +// { +// if((rx_char == ',') || (rx_char == ';') || (rx_char == '?')) /* new field = ,; end of message = ; */ +// { +// /* if(field_index == 0) // message ID received */ +// if(field_index > 0) +// { +// buff->fields[field_index - 1][field_len] = 0; +// } +// +// field_index++; +// field_len = 0; +// +// if(rx_char == ';') +// { +// if(charIndex > LINKBUS_MIN_MSG_LENGTH) +// { +// buff->id = msg_ID; +// } +// receiving_msg = FALSE; +// } +// else if(rx_char == '?') +// { +// buff->type = LINKBUS_MSG_QUERY; +// if(charIndex >= LINKBUS_MIN_MSG_LENGTH) +// { +// buff->id = msg_ID; +// } +// receiving_msg = FALSE; +// } +// +// if(!receiving_msg) +// { +// buff = 0; +// } +// } +// else +// { +// if(field_index == 0) /* message ID received */ +// { +// msg_ID = msg_ID * 10 + rx_char; +// } +// else +// { +// buff->fields[field_index - 1][field_len++] = rx_char; +// } +// } +// } +// else if(rx_char == 0x0D) /* Handle carriage return */ +// { +// buff->id = LINKBUS_MSG_UNKNOWN; +// charIndex = LINKBUS_MAX_MSG_LENGTH; +// field_len = 0; +// msg_ID = LINKBUS_MSG_UNKNOWN; +// field_index = 0; +// buff = NULL; +// } +// +// if(++charIndex >= LINKBUS_MAX_MSG_LENGTH) +// { +// receiving_msg = FALSE; +// charIndex = 0; +// } +// } } } From d5210b08b323c499edc825b84f87f91ed0540c08 Mon Sep 17 00:00:00 2001 From: DigitalConfections Date: Mon, 25 May 2020 22:52:05 -0400 Subject: [PATCH 4/6] Major Revision o Numerous changes o New commands o Bug fixes o Temperature measurement support --- ...lmode-microfox.ino => Arduino-microfox.ino | 2692 ++++++++--------- defs.h | 13 +- linkbus.cpp | 435 +-- linkbus.h | 32 +- 4 files changed, 1601 insertions(+), 1571 deletions(-) rename vhf-allmode-microfox.ino => Arduino-microfox.ino (78%) diff --git a/vhf-allmode-microfox.ino b/Arduino-microfox.ino similarity index 78% rename from vhf-allmode-microfox.ino rename to Arduino-microfox.ino index 721ac51..231aa78 100644 --- a/vhf-allmode-microfox.ino +++ b/Arduino-microfox.ino @@ -1,1360 +1,1332 @@ - -/* */ -/* Microfox Arduino nano version. Converted from PIC C November 2019 */ -/* Jerry Boyd WB8WFK */ -/* This controller will replace the Albuquerque VHF and HF microfox pic based controller */ -/* */ -/* */ - -#include "defs.h" -#include "linkbus.h" -/*#include */ - -#define MAX_PATTERN_TEXT_LENGTH 20 - -volatile int seconds = 0; /* Init timer to first second. Set in ISR checked by main. */ -volatile int minutes = 1; /* Init timer to cycle 1. */ -volatile int g_fox = 0; /* Sets Fox number not set by ISR. Set in startup and checked in main. */ -volatile int active = 0; /* Disable active. set and clear in ISR. Checked in main. */ -volatile int EOC_KEY = 0; /* Used for end of cycle flag. Set in main is cleared in ISR and checked in main. */ -volatile int demo = 0; /* used to put us in ARDF cycle mode sw = 6. */ -volatile int foxO = 0; /* used to put us in fox o mode switch 7. */ - -/*********************************************************************** - * Global Variables & String Constants - * - * Identify each global with a "g_" prefix - * Whenever possible limit globals' scope to this file using "static" - * Use "volatile" for globals shared between ISRs and foreground - ************************************************************************/ -static volatile EC g_last_error_code = ERROR_CODE_NO_ERROR; -static BOOL EEMEM ee_interface_eeprom_initialization_flag = EEPROM_UNINITIALIZED; -static char EEMEM ee_stationID_text[MAX_PATTERN_TEXT_LENGTH + 1]; -static char EEMEM ee_pattern_text[MAX_PATTERN_TEXT_LENGTH + 1]; -static uint8_t EEMEM ee_pattern_codespeed; -static uint8_t EEMEM ee_id_codespeed; -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 char g_messages_text[2][MAX_PATTERN_TEXT_LENGTH + 1] = { "\0", "\0" }; -static volatile uint8_t g_id_codespeed = EEPROM_ID_CODE_SPEED_DEFAULT; -static volatile uint8_t g_pattern_codespeed = EEPROM_PATTERN_CODE_SPEED_DEFAULT; -static volatile uint16_t g_time_needed_for_ID = 0; -static volatile int16_t g_ID_period_seconds = EEPROM_ID_TIME_INTERVAL_DEFAULT; /* amount of time between ID/callsign transmissions */ -static volatile uint16_t g_clock_calibration = EEPROM_CLOCK_CALIBRATION_DEFAULT; -static volatile uint8_t g_override_DIP_switches = EEPROM_OVERRIDE_DIP_SW_DEFAULT; -static volatile uint8_t g_enable_LEDs; - -static char g_tempStr[21] = { '\0' }; - -static volatile uint8_t g_start_override = FALSE; - -/* - * Function Prototypes - */ -void handleLinkBusMsgs(void); -void initializeEEPROMVars(void); -void saveAllEEPROM(void); -void transmitString(char msg[], int speed); -void word_space(int speed); -int codeBits(char alphaNum); - -#ifndef USE_WATCHDOG - void (* resetFunc) (void) = 0; /*declare reset function @ address 0 */ -#endif - -void setup() -{ - initializeEEPROMVars(); /* Initialize variables stored in EEPROM */ - linkbus_init(BAUD); /* Start the Link Bus serial comms */ - linkbus_send_text((char*)"\n\nStored Data:\n"); - sprintf(g_tempStr, " ID: %s\n", g_messages_text[STATION_ID]); - linkbus_send_text(g_tempStr); - sprintf(g_tempStr, " CAL: %u\n", g_clock_calibration); - linkbus_send_text(g_tempStr); - sprintf(g_tempStr, " DIP: %u\n", g_override_DIP_switches); - linkbus_send_text(g_tempStr); - sprintf(g_tempStr, " LED: %s\n", g_enable_LEDs == TRUE ? "ON" : "OFF"); - linkbus_send_text(g_tempStr); - - /* set pins as outputs */ - pinMode(13, OUTPUT); /* The nano amber LED - * This led blinks when off cycle and - * blinks with code when on cycle. */ - pinMode(2, OUTPUT); /* This pin is used to control the KEY line to the transmittter - * only active on cycle. */ - -/* set the pins that are inputs */ - pinMode(3, 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(4, INPUT); /* fox switch LSB */ - pinMode(5, INPUT); /* fox switch middle bit */ - pinMode(6, INPUT); /* fox switch MSB */ - -/* - * read the dip switches and compute the desired fox number - * */ - if(g_override_DIP_switches) - { - g_fox = g_override_DIP_switches; - } - else - { - if(digitalRead(4) == HIGH ) /*Lsb */ - { - g_fox++; - } - if(digitalRead(5) == HIGH ) /* middle bit */ - { - g_fox += 2; - } - if(digitalRead(6) == HIGH ) /* MSB */ - { - g_fox += 4; - } - } - - if(g_fox == 6 ) /* trap for invalid > 6 fox */ - { - demo = 1; /* force to demo mode */ - g_fox = 1; /* start with MOE */ - } - - if(g_fox == 7 ) /* put us in fox O mode */ - { - foxO = 1; /* force to fox O mode */ - } - - cli(); /*stop interrupts for setup */ - - digitalWrite(13, LOW); /* Turn off led sync switch is now open */ - -/* - * get ready set go - * time to start fox operation - * - * The timer came from the below source and I modified it - * for use with microfox. it is the 1 second core timer - * this replaced the PIC timer as the hardware is different. - * ****************************************************** - * timer interrupts - * by Amanda Ghassaei - * June 2012 */ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - */ -/* - * Modifications to the time for microfox done by Jerry Boyd WB8WFK November 2019 - * Removed the unused timers we only use timer 1. - * - * timer setup for timer1, - * For Arduino uno or any board with ATMEL 328/168.. diecimila, duemilanove, lilypad, nano, mini... - * this code will enable arduino timer 1 interrupts. - * timer1 will interrupt at 1Hz - * master variables - * 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 - ** - ** - ************************************************************ - * 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!! - * OCR1A = 15624;// = (16*10^6) / (1*1024) - 1 (must be <65536) //was 15624 for 16.000 MHz on center frequency clock - * OCR1A = 15672;// = (16.043*10^6) / (1*1024) - 1 (must be <65536) //15672 computed for + 16.050 MHz off frequency clock board 4 - * OCR1A = 15661;// = (16.0386*10^6) / (1*1024) - 1 (must be <65536) //15661 computed for + 16.0386 MHz off frequency clock board 3 */ -/* OCR1A = 15629;/ * = (16.006*10^6) / (1*1024) - 1 (must be <65536) //15629 computed for + 16.006 MHz off frequency clock board 3 * / */ - OCR1A = g_clock_calibration; - -/* turn on CTC mode */ - TCCR1B |= (1 << WGM12); -/* Set CS11 bit for 1024 prescaler */ - TCCR1B |= (1 << CS12) | (1 << CS10); -/* enable timer compare interrupt */ - TIMSK1 |= (1 << OCIE1A); - sei(); /*allow interrupts. Arm and run */ - -/* I found this on the web - * note Timer0 - An 8 bit timer used by Arduino functions delay(), millis() and micros(). - * Timer1 - A 16 bit timer used by the Servo() library - * Timer2 - An 8 bit timer used by the Tone() library */ -/* - * we now look for the sync line and then arm the timer interrupts - * when the sync switch is released. - * */ - - linkbus_send_text((char*)"Waiting for sync.\n"); - linkbus_send_text((char*)"Type \"$GO;\"\n"); - - while(( digitalRead(3) == LOW) && !g_start_override) - { - if(g_enable_LEDs) - { - digitalWrite(13, HIGH); /* arduino nano LED - * turn on led to show sync switch is closed */ - } - handleLinkBusMsgs(); - } - - g_start_override = TRUE; - -#ifndef COMPILE_FOR_ARDUINO - loop(); -#endif -}/*end setup */ - - -/*********************************************************************** - * USART Rx Interrupt ISR - * - * This ISR is responsible for reading characters from the USART - * receive buffer to implement the Linkbus. - * - * Message format: - * $id,f1,f2... fn; - * where - * id = Linkbus MessageID - * fn = variable length fields - * ; = end of message flag - * - ************************************************************************/ -ISR(USART_RX_vect) -{ - static char textBuff[LINKBUS_MAX_MSG_FIELD_LENGTH]; - static LinkbusRxBuffer* buff = NULL; - static uint8_t charIndex = 0; - static uint8_t field_index = 0; - static uint8_t field_len = 0; - static uint32_t msg_ID = 0; - static BOOL receiving_msg = FALSE; - uint8_t rx_char; - - rx_char = UDR0; - - if(!buff) - { - buff = nextEmptyRxBuffer(); - } - - if(buff) - { - rx_char = toupper(rx_char); -// SMCR = 0x00; // exit power-down mode - -// if(g_terminal_mode) -// { - static uint8_t ignoreCount = 0; - - if(ignoreCount) - { - rx_char = '\0'; - ignoreCount--; - } - else if(rx_char == 0x1B) /* ESC sequence start */ - { - rx_char = '\0'; - - if(charIndex < LINKBUS_MAX_MSG_FIELD_LENGTH) - { - rx_char = textBuff[charIndex]; - } - - ignoreCount = 2; /* throw out the next two characters */ - } - - if(rx_char == 0x0D) /* Handle carriage return */ - { - if(receiving_msg) - { - if(charIndex > 0) - { - buff->type = LINKBUS_MSG_QUERY; - buff->id = msg_ID; - - if(field_index > 0) /* terminate the last field */ - { - buff->fields[field_index - 1][field_len] = 0; - } - - textBuff[charIndex] = '\0'; /* terminate last-message buffer */ - } - - lb_send_NewLine(); - } - else - { - buff->id = INVALID_MESSAGE; /* print help message */ - } - - charIndex = 0; - field_len = 0; - msg_ID = LINKBUS_MSG_UNKNOWN; - - field_index = 0; - buff = NULL; - - receiving_msg = FALSE; - } - else if(rx_char) - { - textBuff[charIndex] = rx_char; /* hold the characters for re-use */ - - if(charIndex) - { - if(rx_char == 0x7F) /* Handle backspace */ - { - charIndex--; - if(field_index == 0) - { - msg_ID -= textBuff[charIndex]; - msg_ID /= 10; - } - else if(field_len) - { - field_len--; - } - else - { - buff->fields[field_index][0] = '\0'; - field_index--; - } - } - else - { - if(rx_char == ' ') - { - if(textBuff[charIndex - 1] == ' ') - { - rx_char = '\0'; - } - else - { - /* if(field_index == 0) // message ID received */ - if(field_index > 0) - { - buff->fields[field_index - 1][field_len] = 0; - } - - field_index++; - field_len = 0; - } - } - else - { - if(field_index == 0) /* message ID received */ - { - msg_ID = msg_ID * 10 + rx_char; - } - else - { - buff->fields[field_index - 1][field_len++] = rx_char; - } - } - - charIndex = MIN(charIndex+1, LINKBUS_MAX_MSG_FIELD_LENGTH); - } - } - else - { - if((rx_char == 0x7F) || (rx_char == ' ')) /* Handle backspace and Space */ - { - rx_char = '\0'; - } - else /* start of new message */ - { - uint8_t i; - field_index = 0; - msg_ID = 0; - - msg_ID = msg_ID * 10 + rx_char; - - /* Empty the field buffers */ - for(i = 0; i < LINKBUS_MAX_MSG_NUMBER_OF_FIELDS; i++) - { - buff->fields[i][0] = '\0'; - } - - receiving_msg = TRUE; - charIndex = MIN(charIndex+1, LINKBUS_MAX_MSG_FIELD_LENGTH); - } - } - - if(rx_char) - { - lb_echo_char(rx_char); - } - } -// } -// else -// { -// if((rx_char == '$') || (rx_char == '!')) /* start of new message = $ */ -// { -// charIndex = 0; -// buff->type = (rx_char == '!') ? LINKBUS_MSG_REPLY : LINKBUS_MSG_COMMAND; -// field_len = 0; -// msg_ID = LINKBUS_MSG_UNKNOWN; -// receiving_msg = TRUE; -// -// /* Empty the field buffers */ -// for(field_index = 0; field_index < LINKBUS_MAX_MSG_NUMBER_OF_FIELDS; field_index++) -// { -// buff->fields[field_index][0] = '\0'; -// } -// -// field_index = 0; -// } -// else if(receiving_msg) -// { -// if((rx_char == ',') || (rx_char == ';') || (rx_char == '?')) /* new field = ,; end of message = ; */ -// { -// /* if(field_index == 0) // message ID received */ -// if(field_index > 0) -// { -// buff->fields[field_index - 1][field_len] = 0; -// } -// -// field_index++; -// field_len = 0; -// -// if(rx_char == ';') -// { -// if(charIndex > LINKBUS_MIN_MSG_LENGTH) -// { -// buff->id = msg_ID; -// } -// receiving_msg = FALSE; -// } -// else if(rx_char == '?') -// { -// buff->type = LINKBUS_MSG_QUERY; -// if(charIndex >= LINKBUS_MIN_MSG_LENGTH) -// { -// buff->id = msg_ID; -// } -// receiving_msg = FALSE; -// } -// -// if(!receiving_msg) -// { -// buff = 0; -// } -// } -// else -// { -// if(field_index == 0) /* message ID received */ -// { -// msg_ID = msg_ID * 10 + rx_char; -// } -// else -// { -// buff->fields[field_index - 1][field_len++] = rx_char; -// } -// } -// } -// else if(rx_char == 0x0D) /* Handle carriage return */ -// { -// buff->id = LINKBUS_MSG_UNKNOWN; -// charIndex = LINKBUS_MAX_MSG_LENGTH; -// field_len = 0; -// msg_ID = LINKBUS_MSG_UNKNOWN; -// field_index = 0; -// buff = NULL; -// } -// -// if(++charIndex >= LINKBUS_MAX_MSG_LENGTH) -// { -// receiving_msg = FALSE; -// charIndex = 0; -// } -// } - } -} - - -/*********************************************************************** - * USART Tx UDRE ISR - * - * This ISR is responsible for filling the USART transmit buffer. It - * implements the transmit function of the Linkbus. - * - ************************************************************************/ -ISR(USART_UDRE_vect) -{ - static LinkbusTxBuffer* buff = 0; - static uint8_t charIndex = 0; - - if(!buff) - { - buff = nextFullTxBuffer(); - } - - if((*buff)[charIndex]) - { - /* Put data into buffer, sends the data */ - UDR0 = (*buff)[charIndex++]; - } - else - { - charIndex = 0; - (*buff)[0] = '\0'; - buff = nextFullTxBuffer(); - if(!buff) - { - linkbus_end_tx(); - } - } -} - - - -/* - * - * here is our main ISR for the ARDF timer - * 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 */ - -{/*This is the ARDF core timer */ - ++seconds; /* one second event - update seconds */ - -/* - * Code to make home transmitter (MO) cycle work - * this lets transmitter go off for a second and then restart - * by override of the timer in the MO mode. - * */ - if((g_fox == 0) && (minutes > 0)) /* check for override for home transmitter mode - * all other ARDF transmitters use 1,2,3,4,and 5 */ - { - minutes = 0; /* override timer */ - } - -/* normal fox mode (MOx cycle) - * check seconds and update minutes */ - if(seconds == 59) - { - ++minutes; /* make minutes adjustment */ - EOC_KEY = 0; /* flag to kick out of end cycle long tone keydown */ - } - if(seconds == 60) - { - - seconds = 0; /* set seconds back to 0 */ - } - /* adjust timer for cycle */ - if(minutes == 6) /* adjust counter for ARDF cycle */ - { - minutes = 1; /* set for first transmitter */ - } - -/****************************************************** - * - * Code below enables ARDF cycle based on Fox number - * - ****************************************************** */ - - if(g_fox == minutes) /* test for active ARDF cycle */ - { - active = 1; /* active is a flag that the main state machine uses */ - } - else - { - active = 0; - } -} /* end of timer ISR */ - - - -/**************************************************** -** -** Function to send a CW message -** -**************************************************** */ -void Send_Message(int imessage, int speed) -{ - /* Morse Code timing - * Dit = 1 time unit (reference) - * Dah = 3 time units - * Symbol space = 1 time units - * letter Space = 3 time units - * Word space = 7 time units - *{ */ - int time; - - if(imessage == ' ') - { - word_space(speed); - } - else - { - while(1) - { - - if((imessage & 0X01 ) == 0x01) - { - if(g_enable_LEDs) - { - digitalWrite(13, HIGH); /* nano LED */ - } - digitalWrite(2, HIGH); /* TX key line */ - time = speed * 3; - delay(time); - digitalWrite(13, LOW); /* arduino nano LED */ - digitalWrite(2, LOW); /* TX key line */ - - } - else - { - /*OUTPUT_BIT(CW_KEY, 1); // Dit */ - if(g_enable_LEDs) - { - digitalWrite(13, HIGH); /* arduino nano LED */ - } - digitalWrite(2, HIGH); /* TX key line */ - delay(speed); - - digitalWrite(13, LOW); /* arduino nano LED */ - digitalWrite(2, LOW); /* TX key line */ - } - - imessage = imessage >> 1; /* shift right one bit */ - if(imessage == 1) - { - break; /* break the loop */ - } - /*Do a symbol space */ - delay(speed); /*Symbol space */ - } - - /* Do a letter space */ - time = speed * 3; /* */ - delay(time); /*inter character (letter) space */ - } -} - - - -/****************************************** -** -** Function to do a word space based on selected speed -** -****************************************** */ -void word_space(int speed) - -{ - int time; - - time = speed * 7; - delay(time); - - return; -} - - - -/* - * - * here is the main microfox code controller by Jerry Boyd WB8WFK - * - * */ -void loop() -{ - /* put your main code here, to run repeatedly: */ - - int message, id; - int speed; - int fast_speed = 50; /* for last part of cycle */ - int slow_speed = 80; /* for first 30 seconds of cycle */ - int very_fast_speed = 45; /* for CW ID */ - -/* - * - * F O X O MODE - * - * This will place us in fox O mode - * FOX O mode */ - if(foxO == 1) - { - while(1) - { - id = 1; /* id flag */ - speed = 55; - /* do the CW ID for fox O */ - if(id == 1) /* turns on ID for US version */ - { - /* send transmitter call sign - * call sign WB8WFK - * */ - transmitString(g_messages_text[STATION_ID], speed); - id = 0; /* clear ID Flag */ - } /* end of CW ID space */ - - - speed = 70; - while(1) - { - - message = 0x02; /* E */ - Send_Message(message, speed); - word_space(speed); - word_space(speed); - if(seconds > 58) - { - id = 1; - break; - } - handleLinkBusMsgs(); - - } - - - } - - /*********************************************************************** - * Handle arriving Linkbus messages - ************************************************************************/ - } /* end of the fox O loop */ - - -/* - * A R D F cycles MO and DEMO - */ - while(1) /* Start of the standard ARDF and demo mode loop */ - { - /*get ready for first pass - * */ - id = 1; /* set first time pass flag */ - speed = very_fast_speed; /* super Fast ID CW speed */ - /* ID real fast to get past the ID ASAP - * - * ID the transmitter with the call sign - * */ - - while(active) - { - /*Serial.println(seconds); - * Serial.println(minutes); - * Serial.println(active); */ - if(id == 1) /* turns on ID for US version */ - { - /* send transmitter call sign - * call sign WB8WFK - * */ - transmitString(g_messages_text[STATION_ID], speed); - id = 0; /* clear ID Flag */ - } /* end of CW ID space */ - - /************************************************************* - ** - ** now send MOX based on Fox number - ** - ************************************************************* */ - speed = slow_speed; /* Set Slow CW speed for non hams // was 100 - * I.E. boy scouts, school groups - * and Orinereering clubs. - * */ - word_space(speed); /* have a gap between CW ID and first Mox */ - /* - * Main MOX send loop - * */ - while( seconds < 50) - { - if(seconds > 30) /* do we switch CW speed to high speed for hams */ - { /* at 1/2 cycle point */ - speed = fast_speed; /* Yes set fast CW speed for balance of cycle was 55 for pic */ - } /* for hams. */ - - switch(g_fox) /* select the FOX (MOX) to send */ - { - case 0: /* Fox number home */ - { - /* Send MO */ - message = 0x07; /* M */ - Send_Message(message, speed); - word_space(speed); - message = 0x0F; /* O */ - Send_Message(message, speed); - word_space(speed); - handleLinkBusMsgs(); - } - break; - - case 1: /* Fox number 1 */ - { - /* Send MOE */ - message = 0x07; /* M */ - Send_Message(message, speed); - word_space(speed); - message = 0x0F; /* O */ - Send_Message(message, speed); - word_space(speed); - message = 0x02; /* E */ - Send_Message(message, speed); - word_space(speed); - handleLinkBusMsgs(); - } - break; - - case 2: /* Fox number 2 */ - { - /* Send MOI */ - message = 0x07; /* M */ - Send_Message(message, speed); - word_space(speed); - message = 0x0F; /* O */ - Send_Message(message, speed); - word_space(speed); - message = 0x04; /* I */ - Send_Message(message, speed); - word_space(speed); - handleLinkBusMsgs(); - } - break; - - case 3: /* Fox number 3 */ - { - /* Send MOS */ - message = 0x07; /* M */ - Send_Message(message, speed); - word_space(speed); - message = 0x0F; /* O */ - Send_Message(message, speed); - word_space(speed); - message = 0x08; /* S */ - Send_Message(message, speed); - word_space(speed); - handleLinkBusMsgs(); - } - break; - - case 4: /* Fox number 4 */ - { - /* Send MOH */ - message = 0x07; /* M */ - Send_Message(message, speed); - word_space(speed); - message = 0x0F; /* O */ - Send_Message(message, speed); - word_space(speed); - message = 0x10; /* H */ - Send_Message(message, speed); - word_space(speed); - handleLinkBusMsgs(); - } - break; - - case 5: /* Fox number 5 */ - { - /* Send MO5 */ - message = 0x07; /* M */ - Send_Message(message, speed); - word_space(speed); - message = 0x0F; /* O */ - Send_Message(message, speed); - word_space(speed); - message = 0x20; /* 5 */ - Send_Message(message, speed); - word_space(speed); - handleLinkBusMsgs(); - } - break; - } /* end of fox # case test */ - } /* end of mox loop */ - - if((seconds > 50) && (seconds < 55)) /* a window to enter */ - { - /* Signal the end of the cycle - * send a letter C then do the end of cycle tone */ - message = 0x15; /*letter C */ - Send_Message(message, speed); - word_space(speed); - EOC_KEY = 1; /* force a key down for end of cycle */ - /* - * To do. For the Arduino version its possable to add a low battery monitor - * that will turn off the long tone at the end of the cycle to - * aleart the event crew to swap out battery. - * */ - - /******************************************* - ** - ** send the long tone at the - ** end of an ARDF cycle - ** - ******************************************* */ - if(g_enable_LEDs) - { - digitalWrite(13, HIGH); /*arduino turn on end of cycle LED */ - } - digitalWrite(2, HIGH); /*TX key line. Force a EOC key down */ - while(EOC_KEY) - { - /* key down transmitter for end of cycle tone after letter C - * KEYdown was set before entering this loop - * just spend some time here until done */ - - handleLinkBusMsgs(); - } - - digitalWrite(13, LOW); /* arduino turn off end of cycle LED */ - digitalWrite(2, LOW); /* turn off TX key line */ - } /* end of > 50 second checker */ - } /* end of while active loop */ - - /* a trap to walk us through demo mode by cycling fox number */ - if(demo == 1) - { - g_fox++; /* cycle to next one */ - if(g_fox > 5) - { - g_fox = 1; /*reset to 1 */ - } - } - - /* below will flash LED when offcycle for a heartbeat indicator */ - if(g_enable_LEDs) - { - delay(1000); /* delay between offf cycle flash events */ - digitalWrite(13, HIGH); /* arduino flash led when off cycle turn it on */ - delay(100); /* led on time */ - digitalWrite(13, LOW); /* arduino flash led when off cycle turn it off */ - } - - handleLinkBusMsgs(); - } /* end of while 1 loop */ -} - -int codeBits(char alphaNum) -{ - switch(alphaNum) - { - case ' ': - { - return( ' '); - } - - case '0': /* 0 ----- 00111111 0x3F */ - { return( 0x3F); } - - case '1': /* 1 .---- 00111110 0x3E */ - { return( 0x3E); } - - case '2': /* 2 ..--- 00111100 0x3C */ - { return( 0x3C); } - - case '3': /* 3 ...-- 00111000 0x38 */ - { return( 0x38); } - - case '4': /* 4 ....- 00110000 0x30 */ - { return( 0x30); } - - case '5': /* 5 ..... 00100000 0x20 */ - { return( 0x20); } - - case '6': /* 6 -.... 00100001 0x21 */ - { return( 0x21); } - - case '7': /* 7 --... 00100011 0x23 */ - { return( 0x23); } - - case '8': /* 8 ---.. 00100111 0x27 */ - { return( 0x27); } - - case '9': /* 9 ----. 00101111 0x2F */ - { return( 0x2F); } - - case 'A': /* A .- 00000110 0x06 */ - { return( 0x06); } - - case 'B': /* B -... 00010001 0x11 */ - { return( 0x11); } - - case 'C': /* C -.-. 00010101 0x15 */ - { return( 0x15); } - - case 'D': /* D -.. 00001001 0x09 */ - { return( 0x09); } - - case 'E': /* E . 00000010 0x02 */ - { return( 0x02); } - - case 'F': /* F ..-. 00010100 0x14 */ - { return( 0x14); } - - case 'G': /* G --. 00001011 0x0B */ - { return( 0x0B); } - - case 'H': /* H .... 00010000 0x10 */ - { return( 0x10); } - - case 'I': /* I .. 00000100 0x04 */ - { return( 0x04); } - - case 'J': /* J .--- 00011110 0x1E */ - { return( 0x1E); } - - case 'K': /* K -.- 00001101 0x0D */ - { return( 0x0D); } - - case 'L': /* L .-.. 00010010 0x12 */ - { return( 0x12); } - - case 'M': /* M -- 00000111 0x07 */ - { return( 0x07); } - - case 'N': /* N -. 00000101 0x05 */ - { return( 0x05); } - - case 'O': /* O --- 00001111 0x0F */ - { return( 0x0F); } - - case 'P': /* P .--. 00010110 0x16 */ - { return( 0x16); } - - case 'Q': /* Q --.- 00011011 0x1B */ - { return( 0x1B); } - - case 'R': /* R .-. 00001010 0x0A */ - { return( 0x0A); } - - case 'S': /* S ... 00001000 0x08 */ - { return( 0x08); } - - case 'T': /* T - 00000011 0x03 */ - { return( 0x03); } - - case 'U': /* U ..- 00001100 0x0C */ - { return( 0x0C); } - - case 'V': /* V ...- 00011000 0x18 */ - { return( 0x18); } - - case 'W': /* W .-- 00001110 0x0E */ - { return( 0x0E); } - - case 'X': /* X -..- 00011001 0x19 */ - { return( 0x19); } - - case 'Y': /* Y -.-- 00011101 0x1D */ - { return( 0x1D); } - - case 'Z': /* Z --.. 00010011 0x13 */ - { return( 0x13); } - - case '?': /* ? ..--.. 01001100 0x49 Question mark */ - { return( 0x49); } - - default: - return( 0); - } -} - -/* The compiler does not seem to optimize large switch statements correctly */ -void __attribute__((optimize("O0"))) handleLinkBusMsgs() -{ - LinkbusRxBuffer* lb_buff; - BOOL send_ack = TRUE; - - while((lb_buff = nextFullRxBuffer())) - { - LBMessageID msg_id = lb_buff->id; - - switch(msg_id) - { - case MESSAGE_RESET: - { -#ifdef USE_WATCHDOG - wdt_init(WD_FORCE_RESET); - while(1) - { - ; - } -#else - resetFunc(); /*call reset */ -#endif // USE_WATCHDOG - } - break; - - case MESSAGE_OVERRIDE_DIP: - { - if(lb_buff->fields[FIELD1][0]) - { - int d = atoi(lb_buff->fields[FIELD1]); - - if((d >= 0) && (d <= 7)) - { - g_override_DIP_switches = d; - } - - saveAllEEPROM(); - } - - sprintf(g_tempStr, "DIP=%u\n", g_override_DIP_switches); - linkbus_send_text(g_tempStr); - send_ack = FALSE; - } - break; - - case MESSAGE_LEDS: - { - if(lb_buff->fields[FIELD1][0]) - { - if((lb_buff->fields[FIELD1][1] == 'F') || (lb_buff->fields[FIELD1][0] == '0')) - { - g_enable_LEDs = FALSE; - } - else - { - g_enable_LEDs = TRUE; - } - - saveAllEEPROM(); - } - - sprintf(g_tempStr, "LED:%s\n", g_enable_LEDs ? "ON" : "OFF"); - linkbus_send_text(g_tempStr); - send_ack = FALSE; - } - break; - - case MESSAGE_TX_POWER: - { - /* Your code goes here */ - } - break; - - case MESSAGE_PERM: - { - saveAllEEPROM(); - } - break; - - case MESSAGE_GO: - { - if(g_start_override) - { - linkbus_send_text((char*)"Already synced!\n"); - } - else - { - g_start_override = TRUE; - linkbus_send_text((char*)"We're off!\n"); - } - send_ack = FALSE; - } - break; - - case MESSAGE_FACTORY_RESET: - { - 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 - } - break; - - case MESSAGE_CLOCK_CAL: - { - if(lb_buff->fields[FIELD1][0]) - { - uint16_t c = (uint16_t)atoi(lb_buff->fields[FIELD1]); - - if(c > 100) - { - g_clock_calibration = c; - OCR1A = g_clock_calibration; - } - - saveAllEEPROM(); - } - - sprintf(g_tempStr, "Cal=%u\n", g_clock_calibration); - linkbus_send_text(g_tempStr); - send_ack = FALSE; - } - break; - - case MESSAGE_SET_STATION_ID: - { - if(lb_buff->fields[FIELD1][0]) - { - strncpy(g_messages_text[STATION_ID], lb_buff->fields[FIELD1], MAX_PATTERN_TEXT_LENGTH); - - if(g_messages_text[STATION_ID][0]) - { -/* g_time_needed_for_ID = (500 + timeRequiredToSendStrAtWPM(g_messages_text[STATION_ID], g_id_codespeed)) / 1000; */ - } - - saveAllEEPROM(); - } - - sprintf(g_tempStr, "ID:%s\n", g_messages_text[STATION_ID]); - linkbus_send_text(g_tempStr); - send_ack = FALSE; - } - break; - - case MESSAGE_CODE_SPEED: - { - /* Your code goes here */ - } - break; - - case MESSAGE_SET_PATTERN: - { - if(lb_buff->fields[FIELD1][0]) - { - strncpy(g_messages_text[PATTERN_TEXT], lb_buff->fields[FIELD1], MAX_PATTERN_TEXT_LENGTH); - } - } - break; - - case MESSAGE_VERSION: - { - sprintf(g_tempStr, "SW Ver:%u\n", SW_REVISION); - linkbus_send_text(g_tempStr); - send_ack = FALSE; - } - break; - - case MESSAGE_BAT: - { - /* Your code goes here */ - } - break; - - case MESSAGE_TEMP: - { - /* Your code goes here */ - } - break; - - default: - { - linkbus_reset_rx(); /* flush buffer */ - g_last_error_code = ERROR_CODE_ILLEGAL_COMMAND_RCVD; - } - break; - } - - lb_buff->id = (LBMessageID)MESSAGE_EMPTY; - if(send_ack) - { - linkbus_send_text((char*)MESSAGE_ACK); - } - } -} - -void transmitString(char msg[], int speed) -{ - int len = strlen(msg); - - for(int i = 0; i < len; i++) - { - Send_Message(codeBits(msg[i]), speed); - word_space(speed); - } -} - - -/* - * Set EEPROM to its default values - */ -void initializeEEPROMVars() -{ - uint8_t i; - - if(eeprom_read_byte(&ee_interface_eeprom_initialization_flag) == EEPROM_INITIALIZED_FLAG) - { - g_pattern_codespeed = eeprom_read_byte(&ee_pattern_codespeed); - g_id_codespeed = eeprom_read_byte(&ee_id_codespeed); - g_ID_period_seconds = eeprom_read_word(&ee_ID_time); - g_clock_calibration = eeprom_read_word(&ee_clock_calibration); - g_override_DIP_switches = eeprom_read_byte(&ee_override_DIP_switches); - g_enable_LEDs = eeprom_read_byte(&ee_enable_LEDs); - - for(i = 0; i < 20; i++) - { - g_messages_text[STATION_ID][i] = (char)eeprom_read_byte((uint8_t*)(&ee_stationID_text[i])); - if(!g_messages_text[STATION_ID][i]) - { - break; - } - } - - for(i = 0; i < 20; i++) - { - g_messages_text[PATTERN_TEXT][i] = (char)eeprom_read_byte((uint8_t*)(&ee_pattern_text[i])); - if(!g_messages_text[PATTERN_TEXT][i]) - { - break; - } - } - } - else - { - g_id_codespeed = EEPROM_ID_CODE_SPEED_DEFAULT; - g_pattern_codespeed = EEPROM_PATTERN_CODE_SPEED_DEFAULT; - g_ID_period_seconds = EEPROM_ID_TIME_INTERVAL_DEFAULT; - g_clock_calibration = EEPROM_CLOCK_CALIBRATION_DEFAULT; - g_override_DIP_switches = EEPROM_OVERRIDE_DIP_SW_DEFAULT; - g_enable_LEDs = EEPROM_ENABLE_LEDS_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); - saveAllEEPROM(); - eeprom_write_byte(&ee_interface_eeprom_initialization_flag, EEPROM_INITIALIZED_FLAG); - } -} - -/* - * Save all non-volatile values to EEPROM - */ -void saveAllEEPROM() -{ - uint8_t i; - - eeprom_update_byte(&ee_id_codespeed, g_id_codespeed); - eeprom_update_byte(&ee_pattern_codespeed, g_pattern_codespeed); - eeprom_update_word(&ee_ID_time, g_ID_period_seconds); - eeprom_update_word(&ee_clock_calibration, g_clock_calibration); - eeprom_update_byte(&ee_override_DIP_switches, g_override_DIP_switches); - eeprom_update_byte(&ee_enable_LEDs, g_enable_LEDs); - - for(i = 0; i < strlen(g_messages_text[STATION_ID]); i++) - { - eeprom_update_byte((uint8_t*)&ee_stationID_text[i], (uint8_t)g_messages_text[STATION_ID][i]); - } - - eeprom_update_byte((uint8_t*)&ee_stationID_text[i], 0); - - for(i = 0; i < strlen(g_messages_text[PATTERN_TEXT]); i++) - { - eeprom_update_byte((uint8_t*)&ee_pattern_text[i], (uint8_t)g_messages_text[PATTERN_TEXT][i]); - } - - eeprom_update_byte((uint8_t*)&ee_pattern_text[i], 0); -} +/* + * Microfox Arduino nano version. Converted from PIC C November 2019 + * Jerry Boyd WB8WFK + * This controller will replace the Albuquerque VHF and HF microfox pic based controller + * + * */ + +#include "defs.h" +#include "linkbus.h" + +#define MAX_PATTERN_TEXT_LENGTH 20 + +volatile int seconds = 0; /* Init timer to first second. Set in ISR checked by main. */ +volatile int minutes = 1; /* Init timer to cycle 1. */ +volatile int g_fox = 0; /* Sets Fox number not set by ISR. Set in startup and checked in main. */ +volatile int active = 0; /* Disable active. set and clear in ISR. Checked in main. */ +volatile int EOC_KEY = 0; /* Used for end of cycle flag. Set in main is cleared in ISR and checked in main. */ +volatile int demo = 0; /* used to put us in ARDF cycle mode sw = 6. */ +volatile int foxO = 0; /* used to put us in fox o mode switch 7. */ + +/*********************************************************************** + * Global Variables & String Constants + * + * Identify each global with a "g_" prefix + * Whenever possible limit globals' scope to this file using "static" + * Use "volatile" for globals shared between ISRs and foreground + ************************************************************************/ +static volatile EC g_last_error_code = ERROR_CODE_NO_ERROR; +static BOOL EEMEM ee_interface_eeprom_initialization_flag = EEPROM_UNINITIALIZED; +static char EEMEM ee_stationID_text[MAX_PATTERN_TEXT_LENGTH + 1]; +static char EEMEM ee_pattern_text[MAX_PATTERN_TEXT_LENGTH + 1]; +static uint8_t EEMEM ee_pattern_codespeed; +static uint8_t EEMEM ee_id_codespeed; +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 char g_messages_text[2][MAX_PATTERN_TEXT_LENGTH + 1] = { "\0", "\0" }; +static volatile uint8_t g_id_codespeed = EEPROM_ID_CODE_SPEED_DEFAULT; +static volatile uint8_t g_pattern_codespeed = EEPROM_PATTERN_CODE_SPEED_DEFAULT; +static volatile uint16_t g_time_needed_for_ID = 0; +static volatile int16_t g_ID_period_seconds = EEPROM_ID_TIME_INTERVAL_DEFAULT; /* amount of time between ID/callsign transmissions */ +static volatile uint16_t g_clock_calibration = EEPROM_CLOCK_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 char g_tempStr[21] = { '\0' }; + +static volatile uint8_t g_start_override = FALSE; + +/* + * Function Prototypes + */ +void handleLinkBusMsgs(void); +void initializeEEPROMVars(void); +void saveAllEEPROM(void); +void transmitString(char msg[], int speed); +void word_space(int speed); +int codeBits(char alphaNum); +float getTemp(void); +uint16_t readADC(); +void setUpTemp(void); + +#ifndef USE_WATCHDOG + void (* resetFunc) (void) = 0; /*declare reset function @ address 0 */ +#endif + +void setup() +{ + initializeEEPROMVars(); /* Initialize variables stored in EEPROM */ + linkbus_init(BAUD); /* Start the Link Bus serial comms */ + setUpTemp(); + linkbus_send_text((char*)"\n\nStored Data:\n"); + sprintf(g_tempStr, " ID: %s\n", g_messages_text[STATION_ID]); + linkbus_send_text(g_tempStr); + sprintf(g_tempStr, " CAL: %u\n", g_clock_calibration); + linkbus_send_text(g_tempStr); + sprintf(g_tempStr, " DIP: %u\n", g_override_DIP_switches); + linkbus_send_text(g_tempStr); + sprintf(g_tempStr, " LED: %s\n", g_enable_LEDs == TRUE ? "ON" : "OFF"); + linkbus_send_text(g_tempStr); + sprintf(g_tempStr, " SYN: %s\n", g_enable_sync == TRUE ? "ON" : "OFF"); + linkbus_send_text(g_tempStr); + lb_send_NewPrompt(); + + /* set pins as outputs */ + pinMode(13, OUTPUT); /* The nano amber LED + * This led blinks when off cycle and + * blinks with code when on cycle. */ + pinMode(2, OUTPUT); /* This pin is used to control the KEY line to the transmittter + * only active on cycle. */ + +/* set the pins that are inputs */ + pinMode(3, 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(4, INPUT); /* fox switch LSB */ + pinMode(5, INPUT); /* fox switch middle bit */ + pinMode(6, INPUT); /* fox switch MSB */ + +/* + * read the dip switches and compute the desired fox number + * */ + if(g_override_DIP_switches) + { + g_fox = g_override_DIP_switches; + } + else + { + if(digitalRead(4) == HIGH ) /*Lsb */ + { + g_fox++; + } + if(digitalRead(5) == HIGH ) /* middle bit */ + { + g_fox += 2; + } + if(digitalRead(6) == HIGH ) /* MSB */ + { + g_fox += 4; + } + } + + if(g_fox == 6 ) /* trap for invalid > 6 fox */ + { + demo = 1; /* force to demo mode */ + g_fox = 1; /* start with MOE */ + } + + if(g_fox == 7 ) /* put us in fox O mode */ + { + foxO = 1; /* force to fox O mode */ + } + + cli(); /*stop interrupts for setup */ + + digitalWrite(13, LOW); /* Turn off led sync switch is now open */ + +/* + * get ready set go + * time to start fox operation + * + * The timer came from the below source and I modified it + * for use with microfox. it is the 1 second core timer + * this replaced the PIC timer as the hardware is different. + * ****************************************************** + * timer interrupts + * by Amanda Ghassaei + * June 2012 */ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + */ +/* + * Modifications to the time for microfox done by Jerry Boyd WB8WFK November 2019 + * Removed the unused timers we only use timer 1. + * + * timer setup for timer1, + * For Arduino uno or any board with ATMEL 328/168.. diecimila, duemilanove, lilypad, nano, mini... + * this code will enable arduino timer 1 interrupts. + * timer1 will interrupt at 1Hz + * master variables + * 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 + ** + ** + ************************************************************ + * 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!! + * OCR1A = 15624;// = (16*10^6) / (1*1024) - 1 (must be <65536) //was 15624 for 16.000 MHz on center frequency clock + * OCR1A = 15672;// = (16.043*10^6) / (1*1024) - 1 (must be <65536) //15672 computed for + 16.050 MHz off frequency clock board 4 + * OCR1A = 15661;// = (16.0386*10^6) / (1*1024) - 1 (must be <65536) //15661 computed for + 16.0386 MHz off frequency clock board 3 */ +/* OCR1A = 15629;/ * = (16.006*10^6) / (1*1024) - 1 (must be <65536) //15629 computed for + 16.006 MHz off frequency clock board 3 * / */ + OCR1A = g_clock_calibration; + +/* turn on CTC mode */ + TCCR1B |= (1 << WGM12); +/* Set CS11 bit for 1024 prescaler */ + TCCR1B |= (1 << CS12) | (1 << CS10); +/* enable timer compare interrupt */ + TIMSK1 |= (1 << OCIE1A); + sei(); /*allow interrupts. Arm and run */ + +/* I found this on the web + * note Timer0 - An 8 bit timer used by Arduino functions delay(), millis() and micros(). + * Timer1 - A 16 bit timer used by the Servo() library + * Timer2 - An 8 bit timer used by the Tone() library */ +/* + * we now look for the sync line and then arm the timer interrupts + * when the sync switch is released. + * */ + + if(g_enable_sync) + { + linkbus_send_text((char*)"Waiting for sync.\n"); + linkbus_send_text((char*)"Type \"GO\"\n"); + lb_send_NewPrompt(); + + while(( digitalRead(3) == LOW) && !g_start_override) + { + if(g_enable_LEDs) + { + digitalWrite(13, HIGH); /* arduino nano LED + * turn on led to show sync switch is closed */ + } + + minutes = 1; /* Reset the clock start of cycle addresses different power up times*/ + seconds = 0; /* Reset the clock addresses different power up times*/ + handleLinkBusMsgs(); + } + } + else + { + linkbus_send_text((char*)"Tx is running!\n"); + lb_send_NewPrompt(); + } + + g_start_override = TRUE; + +#ifndef COMPILE_FOR_ARDUINO + loop(); +#endif +}/*end setup */ + + +/*********************************************************************** + * USART Rx Interrupt ISR + * + * This ISR is responsible for reading characters from the USART + * receive buffer to implement the Linkbus. + * + * Message format: + * $id,f1,f2... fn; + * where + * id = Linkbus MessageID + * fn = variable length fields + * ; = end of message flag + * + ************************************************************************/ +ISR(USART_RX_vect) +{ + static char textBuff[LINKBUS_MAX_MSG_FIELD_LENGTH]; + static LinkbusRxBuffer* buff = NULL; + static uint8_t charIndex = 0; + static uint8_t field_index = 0; + static uint8_t field_len = 0; + static int msg_ID = 0; + static BOOL receiving_msg = FALSE; + uint8_t rx_char; + + rx_char = UDR0; + + if(!buff) + { + buff = nextEmptyRxBuffer(); + } + + if(buff) + { + rx_char = toupper(rx_char); +/* SMCR = 0x00; // exit power-down mode */ + +/* if(g_terminal_mode) + * { */ + static uint8_t ignoreCount = 0; + + if(ignoreCount) + { + rx_char = '\0'; + ignoreCount--; + } + else if(rx_char == 0x1B) /* ESC sequence start */ + { + rx_char = '\0'; + + if(charIndex < LINKBUS_MAX_MSG_FIELD_LENGTH) + { + rx_char = textBuff[charIndex]; + } + + ignoreCount = 2; /* throw out the next two characters */ + } + + if(rx_char == 0x0D) /* Handle carriage return */ + { + if(receiving_msg) + { + if(charIndex > 0) + { + buff->type = LINKBUS_MSG_QUERY; + buff->id = (LBMessageID)msg_ID; + + if(field_index > 0) /* terminate the last field */ + { + buff->fields[field_index - 1][field_len] = 0; + } + + textBuff[charIndex] = '\0'; /* terminate last-message buffer */ + } + + lb_send_NewLine(); + } + else + { + buff->id = INVALID_MESSAGE; /* print help message */ + } + + charIndex = 0; + field_len = 0; + msg_ID = MESSAGE_EMPTY; + + field_index = 0; + buff = NULL; + + receiving_msg = FALSE; + } + else if(rx_char) + { + textBuff[charIndex] = rx_char; /* hold the characters for re-use */ + + if(charIndex) + { + if(rx_char == 0x7F) /* Handle backspace */ + { + charIndex--; + if(field_index == 0) + { + msg_ID -= textBuff[charIndex]; + msg_ID /= 10; + } + else if(field_len) + { + field_len--; + } + else + { + buff->fields[field_index][0] = '\0'; + field_index--; + } + } + else + { + if(rx_char == ' ') + { + if(textBuff[charIndex - 1] == ' ') + { + rx_char = '\0'; + } + else + { + /* if(field_index == 0) // message ID received */ + if(field_index > 0) + { + buff->fields[field_index - 1][field_len] = 0; + } + + field_index++; + field_len = 0; + } + } + else + { + if(field_index == 0) /* message ID received */ + { + msg_ID = msg_ID * 10 + rx_char; + } + else + { + buff->fields[field_index - 1][field_len++] = rx_char; + } + } + + charIndex = MIN(charIndex + 1, LINKBUS_MAX_MSG_FIELD_LENGTH); + } + } + else + { + if((rx_char == 0x7F) || (rx_char == ' ')) /* Handle backspace and Space */ + { + rx_char = '\0'; + } + else /* start of new message */ + { + uint8_t i; + field_index = 0; + msg_ID = 0; + + msg_ID = msg_ID * 10 + rx_char; + + /* Empty the field buffers */ + for(i = 0; i < LINKBUS_MAX_MSG_NUMBER_OF_FIELDS; i++) + { + buff->fields[i][0] = '\0'; + } + + receiving_msg = TRUE; + charIndex = MIN(charIndex + 1, LINKBUS_MAX_MSG_FIELD_LENGTH); + } + } + + if(rx_char) + { + lb_echo_char(rx_char); + } + } + } +} + + +/*********************************************************************** + * USART Tx UDRE ISR + * + * This ISR is responsible for filling the USART transmit buffer. It + * implements the transmit function of the Linkbus. + * + ************************************************************************/ +ISR(USART_UDRE_vect) +{ + static LinkbusTxBuffer* buff = 0; + static uint8_t charIndex = 0; + + if(!buff) + { + buff = nextFullTxBuffer(); + } + + if((*buff)[charIndex]) + { + /* Put data into buffer, sends the data */ + UDR0 = (*buff)[charIndex++]; + } + else + { + charIndex = 0; + (*buff)[0] = '\0'; + buff = nextFullTxBuffer(); + if(!buff) + { + linkbus_end_tx(); + } + } +} + + + +/* + * + * here is our main ISR for the ARDF timer + * 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 */ + +{/*This is the ARDF core timer */ + ++seconds; /* one second event - update seconds */ + +/* + * Code to make home transmitter (MO) cycle work + * this lets transmitter go off for a second and then restart + * by override of the timer in the MO mode. + * */ + if((g_fox == 0) && (minutes > 0)) /* check for override for home transmitter mode + * all other ARDF transmitters use 1,2,3,4,and 5 */ + { + minutes = 0; /* override timer */ + } + +/* normal fox mode (MOx cycle) + * check seconds and update minutes */ + if(seconds == 59) + { + ++minutes; /* make minutes adjustment */ + EOC_KEY = 0; /* flag to kick out of end cycle long tone keydown */ + } + if(seconds == 60) + { + + seconds = 0; /* set seconds back to 0 */ + } + /* adjust timer for cycle */ + if(minutes == 6) /* adjust counter for ARDF cycle */ + { + minutes = 1; /* set for first transmitter */ + } + +/****************************************************** + * + * Code below enables ARDF cycle based on Fox number + * + ****************************************************** */ + + if(g_fox == minutes) /* test for active ARDF cycle */ + { + active = 1; /* active is a flag that the main state machine uses */ + } + else + { + active = 0; + } +} /* end of timer ISR */ + + + +/**************************************************** +** +** Function to send a CW message +** +**************************************************** */ +void Send_Message(int imessage, int speed) +{ + /* Morse Code timing + * Dit = 1 time unit (reference) + * Dah = 3 time units + * Symbol space = 1 time units + * letter Space = 3 time units + * Word space = 7 time units + *{ */ + int time; + + if(imessage == ' ') + { + word_space(speed); + } + else + { + while(1) + { + /* + * A trap to catch the condition where number 5 is same as ASCII space + * changed encoding in code table to set MSB for # 5 as a workaround + */ + if(imessage == TX5) + { + imessage = 0x20; /* set it back to this so this loop will encode a number 5 */ + } + + if((imessage & 0X01 ) == 0x01) + { + if(g_enable_LEDs) + { + digitalWrite(13, HIGH); /* nano LED */ + } + digitalWrite(2, HIGH); /* TX key line */ + time = speed * 3; + delay(time); + digitalWrite(13, LOW); /* arduino nano LED */ + digitalWrite(2, LOW); /* TX key line */ + + } + else + { + /*OUTPUT_BIT(CW_KEY, 1); // Dit */ + if(g_enable_LEDs) + { + digitalWrite(13, HIGH); /* arduino nano LED */ + } + digitalWrite(2, HIGH); /* TX key line */ + delay(speed); + + digitalWrite(13, LOW); /* arduino nano LED */ + digitalWrite(2, LOW); /* TX key line */ + } + + imessage = imessage >> 1; /* shift right one bit */ + if(imessage == 1) + { + break; /* break the loop */ + } + /*Do a symbol space */ + delay(speed); /*Symbol space */ + } + + /* Do a letter space */ + time = speed * 3; /* */ + delay(time); /*inter character (letter) space */ + } +} + + + +/****************************************** +** +** Function to do a word space based on selected speed +** +****************************************** */ +void word_space(int speed) +{ + int time; + + time = speed * 7; + delay(time); + + return; +} + + + +/* + * + * here is the main microfox code controller by Jerry Boyd WB8WFK + * + * */ +void loop() +{ + /* put your main code here, to run repeatedly: */ + + int message, id; + int speed; + int fast_speed = 50; /* for last part of cycle */ + int slow_speed = 80; /* for first 30 seconds of cycle */ + int very_fast_speed = 45; /* for CW ID */ + +/* + * + * F O X O MODE + * + * This will place us in fox O mode + * FOX O mode */ + if(foxO == 1) + { + while(1) + { + id = 1; /* id flag */ + speed = 55; + /* do the CW ID for fox O */ + if(id == 1) /* turns on ID for US version */ + { + /* send transmitter call sign + * call sign WB8WFK + * */ + transmitString(g_messages_text[STATION_ID], speed); + id = 0; /* clear ID Flag */ + } /* end of CW ID space */ + + + speed = 70; + while(1) + { + + message = 0x02; /* E */ + Send_Message(message, speed); + word_space(speed); + word_space(speed); + if(seconds > 58) + { + id = 1; + break; + } + handleLinkBusMsgs(); + + } + + + } + + /*********************************************************************** + * Handle arriving Linkbus messages + ************************************************************************/ + } /* end of the fox O loop */ + + +/* + * A R D F cycles MO and DEMO + */ + while(1) /* Start of the standard ARDF and demo mode loop */ + { + /*get ready for first pass + * */ + id = 1; /* set first time pass flag */ + speed = very_fast_speed; /* super Fast ID CW speed */ + /* ID real fast to get past the ID ASAP + * + * ID the transmitter with the call sign + * */ + + while(active) + { + /*Serial.println(seconds); + * Serial.println(minutes); + * Serial.println(active); */ + if(id == 1) /* turns on ID for US version */ + { + /* send transmitter call sign + * call sign WB8WFK + * */ + transmitString(g_messages_text[STATION_ID], speed); + id = 0; /* clear ID Flag */ + } /* end of CW ID space */ + + /************************************************************* + ** + ** now send MOX based on Fox number + ** + ************************************************************* */ + speed = slow_speed; /* Set Slow CW speed for non hams // was 100 + * I.E. boy scouts, school groups + * and Orinereering clubs. + * */ + word_space(speed); /* have a gap between CW ID and first Mox */ + /* + * Main MOX send loop + * */ + while( seconds < 50) + { + if(seconds > 30) /* do we switch CW speed to high speed for hams */ + { /* at 1/2 cycle point */ + speed = fast_speed; /* Yes set fast CW speed for balance of cycle was 55 for pic */ + } /* for hams. */ + + switch(g_fox) /* select the FOX (MOX) to send */ + { + case 0: /* Fox number home */ + { + /* Send MO */ + message = 0x07; /* M */ + Send_Message(message, speed); + word_space(speed); + message = 0x0F; /* O */ + Send_Message(message, speed); + word_space(speed); + handleLinkBusMsgs(); + } + break; + + case 1: /* Fox number 1 */ + { + /* Send MOE */ + message = 0x07; /* M */ + Send_Message(message, speed); + word_space(speed); + message = 0x0F; /* O */ + Send_Message(message, speed); + word_space(speed); + message = 0x02; /* E */ + Send_Message(message, speed); + word_space(speed); + handleLinkBusMsgs(); + } + break; + + case 2: /* Fox number 2 */ + { + /* Send MOI */ + message = 0x07; /* M */ + Send_Message(message, speed); + word_space(speed); + message = 0x0F; /* O */ + Send_Message(message, speed); + word_space(speed); + message = 0x04; /* I */ + Send_Message(message, speed); + word_space(speed); + handleLinkBusMsgs(); + } + break; + + case 3: /* Fox number 3 */ + { + /* Send MOS */ + message = 0x07; /* M */ + Send_Message(message, speed); + word_space(speed); + message = 0x0F; /* O */ + Send_Message(message, speed); + word_space(speed); + message = 0x08; /* S */ + Send_Message(message, speed); + word_space(speed); + handleLinkBusMsgs(); + } + break; + + case 4: /* Fox number 4 */ + { + /* Send MOH */ + message = 0x07; /* M */ + Send_Message(message, speed); + word_space(speed); + message = 0x0F; /* O */ + Send_Message(message, speed); + word_space(speed); + message = 0x10; /* H */ + Send_Message(message, speed); + word_space(speed); + handleLinkBusMsgs(); + } + break; + + case 5: /* Fox number 5 */ + { + /* Send MO5 */ + message = 0x07; /* M */ + Send_Message(message, speed); + word_space(speed); + message = 0x0F; /* O */ + Send_Message(message, speed); + word_space(speed); + message = TX5; /* 5 make A0 so to get around space issue */ + Send_Message(message, speed); + word_space(speed); + handleLinkBusMsgs(); + } + break; + } /* end of fox # case test */ + } /* end of mox loop */ + + if((seconds > 50) && (seconds < 55)) /* a window to enter */ + { + /* Signal the end of the cycle + * send a letter C then do the end of cycle tone */ + message = 0x15; /*letter C */ + Send_Message(message, speed); + word_space(speed); + EOC_KEY = 1; /* force a key down for end of cycle */ + /* + * To do. For the Arduino version its possable to add a low battery monitor + * that will turn off the long tone at the end of the cycle to + * aleart the event crew to swap out battery. + * */ + + /******************************************* + ** + ** send the long tone at the + ** end of an ARDF cycle + ** + ******************************************* */ + if(g_enable_LEDs) + { + digitalWrite(13, HIGH); /*arduino turn on end of cycle LED */ + } + digitalWrite(2, HIGH); /*TX key line. Force a EOC key down */ + while(EOC_KEY) + { + /* key down transmitter for end of cycle tone after letter C + * KEYdown was set before entering this loop + * just spend some time here until done */ + + handleLinkBusMsgs(); + } + + digitalWrite(13, LOW); /* arduino turn off end of cycle LED */ + digitalWrite(2, LOW); /* turn off TX key line */ + } /* end of > 50 second checker */ + } /* end of while active loop */ + + /* a trap to walk us through demo mode by cycling fox number */ + if(demo == 1) + { + g_fox++; /* cycle to next one */ + if(g_fox > 5) + { + g_fox = 1; /*reset to 1 */ + } + } + + /* below will flash LED when offcycle for a heartbeat indicator */ + if(g_enable_LEDs) + { + delay(1000); /* delay between offf cycle flash events */ + digitalWrite(13, HIGH); /* arduino flash led when off cycle turn it on */ + delay(100); /* led on time */ + digitalWrite(13, LOW); /* arduino flash led when off cycle turn it off */ + } + + handleLinkBusMsgs(); + } /* end of while 1 loop */ +} + +int codeBits(char alphaNum) +{ + switch(alphaNum) + { + case ' ': + { + return( ' '); + } + + case '0': /* 0 ----- 00111111 0x3F */ + { return( 0x3F); } + + case '1': /* 1 .---- 00111110 0x3E */ + { return( 0x3E); } + + case '2': /* 2 ..--- 00111100 0x3C */ + { return( 0x3C); } + + case '3': /* 3 ...-- 00111000 0x38 */ + { return( 0x38); } + + case '4': /* 4 ....- 00110000 0x30 */ + { return( 0x30); } + + case '5': /* 5 ..... 00100000 0x20 make 10100000 0xA0 so its not same as ASCII space and mask out upper bit and trap in send message to make back to 0x20*/ + { return( TX5); } + + case '6': /* 6 -.... 00100001 0x21 */ + { return( 0x21); } + + case '7': /* 7 --... 00100011 0x23 */ + { return( 0x23); } + + case '8': /* 8 ---.. 00100111 0x27 */ + { return( 0x27); } + + case '9': /* 9 ----. 00101111 0x2F */ + { return( 0x2F); } + + case 'A': /* A .- 00000110 0x06 */ + { return( 0x06); } + + case 'B': /* B -... 00010001 0x11 */ + { return( 0x11); } + + case 'C': /* C -.-. 00010101 0x15 */ + { return( 0x15); } + + case 'D': /* D -.. 00001001 0x09 */ + { return( 0x09); } + + case 'E': /* E . 00000010 0x02 */ + { return( 0x02); } + + case 'F': /* F ..-. 00010100 0x14 */ + { return( 0x14); } + + case 'G': /* G --. 00001011 0x0B */ + { return( 0x0B); } + + case 'H': /* H .... 00010000 0x10 */ + { return( 0x10); } + + case 'I': /* I .. 00000100 0x04 */ + { return( 0x04); } + + case 'J': /* J .--- 00011110 0x1E */ + { return( 0x1E); } + + case 'K': /* K -.- 00001101 0x0D */ + { return( 0x0D); } + + case 'L': /* L .-.. 00010010 0x12 */ + { return( 0x12); } + + case 'M': /* M -- 00000111 0x07 */ + { return( 0x07); } + + case 'N': /* N -. 00000101 0x05 */ + { return( 0x05); } + + case 'O': /* O --- 00001111 0x0F */ + { return( 0x0F); } + + case 'P': /* P .--. 00010110 0x16 */ + { return( 0x16); } + + case 'Q': /* Q --.- 00011011 0x1B */ + { return( 0x1B); } + + case 'R': /* R .-. 00001010 0x0A */ + { return( 0x0A); } + + case 'S': /* S ... 00001000 0x08 */ + { return( 0x08); } + + case 'T': /* T - 00000011 0x03 */ + { return( 0x03); } + + case 'U': /* U ..- 00001100 0x0C */ + { return( 0x0C); } + + case 'V': /* V ...- 00011000 0x18 */ + { return( 0x18); } + + case 'W': /* W .-- 00001110 0x0E */ + { return( 0x0E); } + + case 'X': /* X -..- 00011001 0x19 */ + { return( 0x19); } + + case 'Y': /* Y -.-- 00011101 0x1D */ + { return( 0x1D); } + + case 'Z': /* Z --.. 00010011 0x13 */ + { return( 0x13); } + + case '?': /* ? ..--.. 01001100 0x49 Question mark */ + { return( 0x49); } + + default: + return( 0); + } +} + +/* The compiler does not seem to optimize large switch statements correctly */ +void __attribute__((optimize("O0"))) handleLinkBusMsgs() +{ + LinkbusRxBuffer* lb_buff; + BOOL send_ack = TRUE; + + while((lb_buff = nextFullRxBuffer())) + { + LBMessageID msg_id = lb_buff->id; + + switch(msg_id) + { + case MESSAGE_RESET: + { +#ifdef USE_WATCHDOG + wdt_init(WD_FORCE_RESET); + while(1) + { + ; + } +#else + resetFunc(); /*call reset */ +#endif /* USE_WATCHDOG */ + } + break; + + case MESSAGE_OVERRIDE_DIP: + { + if(lb_buff->fields[FIELD1][0]) + { + int d = atoi(lb_buff->fields[FIELD1]); + + if((d >= 0) && (d <= 7)) + { + g_override_DIP_switches = d; + } + + saveAllEEPROM(); + } + + sprintf(g_tempStr, "DIP=%u\n", g_override_DIP_switches); + linkbus_send_text(g_tempStr); + } + break; + + case MESSAGE_LEDS: + { + if(lb_buff->fields[FIELD1][0]) + { + if((lb_buff->fields[FIELD1][1] == 'F') || (lb_buff->fields[FIELD1][0] == '0')) + { + g_enable_LEDs = FALSE; + } + else + { + g_enable_LEDs = TRUE; + } + + saveAllEEPROM(); + } + + sprintf(g_tempStr, "LED:%s\n", g_enable_LEDs ? "ON" : "OFF"); + linkbus_send_text(g_tempStr); + } + 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"); + linkbus_send_text(g_tempStr); + } + break; + + case MESSAGE_GO: + { + if(g_start_override) + { + linkbus_send_text((char*)"Already synced!\n"); + } + else + { + g_start_override = TRUE; + linkbus_send_text((char*)"We're off!\n"); + } + } + break; + + case MESSAGE_FACTORY_RESET: + { + 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 */ + } + break; + + case MESSAGE_CLOCK_CAL: + { + if(lb_buff->fields[FIELD1][0]) + { + uint16_t c = (uint16_t)atoi(lb_buff->fields[FIELD1]); + + if(c > 100) + { + g_clock_calibration = c; + OCR1A = g_clock_calibration; + } + + saveAllEEPROM(); + } + + sprintf(g_tempStr, "Cal=%u\n", g_clock_calibration); + linkbus_send_text(g_tempStr); + } + break; + + case MESSAGE_SET_STATION_ID: + { + if(lb_buff->fields[FIELD1][0]) + { + strncpy(g_messages_text[STATION_ID], lb_buff->fields[FIELD1], MAX_PATTERN_TEXT_LENGTH); + + if(g_messages_text[STATION_ID][0]) + { +/* g_time_needed_for_ID = (500 + timeRequiredToSendStrAtWPM(g_messages_text[STATION_ID], g_id_codespeed)) / 1000; */ + } + + saveAllEEPROM(); + } + + sprintf(g_tempStr, "ID:%s\n", g_messages_text[STATION_ID]); + linkbus_send_text(g_tempStr); + } + break; + + case MESSAGE_VERSION: + { + sprintf(g_tempStr, "SW Ver:%s\n", SW_REVISION); + linkbus_send_text(g_tempStr); + } + break; + + case MESSAGE_TEMP: + { + float temp = getTemp(); + sprintf(g_tempStr, "Temp: %dC\n", (int)temp); + linkbus_send_text(g_tempStr); + } + break; + + default: + { + lb_send_Help(); + } + break; + } + + lb_buff->id = (LBMessageID)MESSAGE_EMPTY; + if(send_ack) + { + lb_send_NewPrompt(); + } + } +} + +void transmitString(char msg[], int speed) +{ + int len = strlen(msg); + + for(int i = 0; i < len; i++) + { + Send_Message(codeBits(msg[i]), speed); + word_space(speed); + } +} + + +/* + * Set EEPROM to its default values + */ +void initializeEEPROMVars() +{ + uint8_t i; + + if(eeprom_read_byte(&ee_interface_eeprom_initialization_flag) == EEPROM_INITIALIZED_FLAG) + { + g_pattern_codespeed = eeprom_read_byte(&ee_pattern_codespeed); + g_id_codespeed = eeprom_read_byte(&ee_id_codespeed); + g_ID_period_seconds = eeprom_read_word(&ee_ID_time); + g_clock_calibration = eeprom_read_word(&ee_clock_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); + + for(i = 0; i < 20; i++) + { + g_messages_text[STATION_ID][i] = (char)eeprom_read_byte((uint8_t*)(&ee_stationID_text[i])); + if(!g_messages_text[STATION_ID][i]) + { + break; + } + } + + for(i = 0; i < 20; i++) + { + g_messages_text[PATTERN_TEXT][i] = (char)eeprom_read_byte((uint8_t*)(&ee_pattern_text[i])); + if(!g_messages_text[PATTERN_TEXT][i]) + { + break; + } + } + } + else + { + g_id_codespeed = EEPROM_ID_CODE_SPEED_DEFAULT; + g_pattern_codespeed = EEPROM_PATTERN_CODE_SPEED_DEFAULT; + g_ID_period_seconds = EEPROM_ID_TIME_INTERVAL_DEFAULT; + g_clock_calibration = EEPROM_CLOCK_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; + 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); + saveAllEEPROM(); + eeprom_write_byte(&ee_interface_eeprom_initialization_flag, EEPROM_INITIALIZED_FLAG); + } +} + +/* + * Save all non-volatile values to EEPROM + */ +void saveAllEEPROM() +{ + uint8_t i; + + eeprom_update_byte(&ee_id_codespeed, g_id_codespeed); + eeprom_update_byte(&ee_pattern_codespeed, g_pattern_codespeed); + eeprom_update_word(&ee_ID_time, g_ID_period_seconds); + eeprom_update_word(&ee_clock_calibration, g_clock_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); + + for(i = 0; i < strlen(g_messages_text[STATION_ID]); i++) + { + eeprom_update_byte((uint8_t*)&ee_stationID_text[i], (uint8_t)g_messages_text[STATION_ID][i]); + } + + eeprom_update_byte((uint8_t*)&ee_stationID_text[i], 0); + + for(i = 0; i < strlen(g_messages_text[PATTERN_TEXT]); i++) + { + eeprom_update_byte((uint8_t*)&ee_pattern_text[i], (uint8_t)g_messages_text[PATTERN_TEXT][i]); + } + + eeprom_update_byte((uint8_t*)&ee_pattern_text[i], 0); +} + +void setUpTemp(void) +{ + /* The internal temperature has to be used + * with the internal reference of 1.1V. + * Channel 8 can not be selected with + * the analogRead function yet. */ + /* Set the internal reference and mux. */ + ADMUX = ((1 << REFS1) | (1 << REFS0) | (1 << MUX3)); + + /* Slow the ADC clock down to 125 KHz + * by dividing by 128. Assumes that the + * standard Arduino 16 MHz clock is in use. */ + ADCSRA = (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0); + + ADCSRA |= (1 << ADEN); /* enable the ADC */ + + delay(200); /* wait for voltages to become stable. */ + + ADCSRA |= (1 << ADSC); /* Start the ADC */ + + readADC(); +} + +uint16_t readADC() +{ + /* Make sure the most recent ADC read is complete. */ + while((ADCSRA & (1 << ADSC))) + { + ; /* Just wait for ADC to finish. */ + } + uint16_t result = ADCW; + /* Initiate another reading. */ + ADCSRA |= (1 << ADSC); + return( result); +} + +float getTemp(void) +{ + /* The offset (first term) was determined empirically */ + readADC(); /* throw away first reading */ + return(14.7 + (readADC() - 324.31) / 1.22); +} diff --git a/defs.h b/defs.h index 654e61f..f639927 100644 --- a/defs.h +++ b/defs.h @@ -36,7 +36,7 @@ //#define TRANQUILIZE_WATCHDOG #define PRODUCT_NAME_SHORT "ARDF Tx" -#define PRODUCT_NAME_LONG "ARDF Dual-Band Transmitter" +#define PRODUCT_NAME_LONG "WB8WFK ARDF Transmitter" /*******************************************************/ @@ -65,6 +65,14 @@ typedef unsigned char uint8_t; #define BIAS_DAC DAC081C_I2C_SLAVE_ADDR_A2 #endif +typedef enum { +// TX1 = 0xA4, +// TX2 = 0xA3, +// TX3 = 0xA2, +// TX4 = 0xA1, + TX5 = 0xA0 + } Tx_t; + /*******************************************************/ /* Error Codes */ /*******************************************************/ @@ -157,7 +165,7 @@ typedef uint16_t BatteryLevel; /* in milliVolts */ /****************************************************** * EEPROM definitions */ -#define EEPROM_INITIALIZED_FLAG 0xAC +#define EEPROM_INITIALIZED_FLAG 0xAD #define EEPROM_UNINITIALIZED 0x00 #define EEPROM_STATION_ID_DEFAULT "FOXBOX" @@ -175,6 +183,7 @@ typedef uint16_t BatteryLevel; /* in milliVolts */ #define EEPROM_CLOCK_CALIBRATION_DEFAULT 15629 #define EEPROM_OVERRIDE_DIP_SW_DEFAULT 0 #define EEPROM_ENABLE_LEDS_DEFAULT 1 +#define EEPROM_ENABLE_SYNC_DEFAULT 1 #define EEPROM_SI5351_CALIBRATION_DEFAULT 0x00 #define EEPROM_CLK0_OUT_DEFAULT 133000000 diff --git a/linkbus.cpp b/linkbus.cpp index b00c890..d1b2fc8 100644 --- a/linkbus.cpp +++ b/linkbus.cpp @@ -25,7 +25,6 @@ #include "linkbus.h" #include "defs.h" - //#include "util.h" //#include //#include @@ -35,7 +34,18 @@ static volatile BOOL g_bus_disabled = TRUE; static const char crlf[] = "\n"; static char lineTerm[8] = "\n"; -static const char textPrompt[] = "TX> "; +static const char textPrompt[] = "> "; + +static const char textHelp[][LINKBUS_MAX_TX_MSG_LENGTH] = { "\nCommands:\n", + " CAL - Calibrate\n", + " DIP - Override DIP\n", + " FAC - Factory reset\n", + " GO - Sync clock\n", + " ID - Set callsign\n", + " LED - LED on/off\n", + " RST - Reset\n", + " SYN - Sync on/off\n", + " VER - S/W version\n" }; static char g_tempMsgBuff[LINKBUS_MAX_MSG_LENGTH]; @@ -43,124 +53,124 @@ static char g_tempMsgBuff[LINKBUS_MAX_MSG_LENGTH]; BOOL linkbus_start_tx(void); /* Module global variables */ -static volatile BOOL linkbus_tx_active = FALSE; // volatile is required to ensure optimizer handles this properly +static volatile BOOL linkbus_tx_active = FALSE; /* volatile is required to ensure optimizer handles this properly */ static LinkbusTxBuffer tx_buffer[LINKBUS_NUMBER_OF_TX_MSG_BUFFERS]; static LinkbusRxBuffer rx_buffer[LINKBUS_NUMBER_OF_RX_MSG_BUFFERS]; LinkbusTxBuffer* nextFullTxBuffer(void) { - BOOL found = TRUE; - static uint8_t bufferIndex = 0; - uint8_t count = 0; + BOOL found = TRUE; + static uint8_t bufferIndex = 0; + uint8_t count = 0; - while(tx_buffer[bufferIndex][0] == '\0') - { - if(++count >= LINKBUS_NUMBER_OF_TX_MSG_BUFFERS) - { - found = FALSE; - break; - } + while(tx_buffer[bufferIndex][0] == '\0') + { + if(++count >= LINKBUS_NUMBER_OF_TX_MSG_BUFFERS) + { + found = FALSE; + break; + } - bufferIndex++; - if(bufferIndex >= LINKBUS_NUMBER_OF_TX_MSG_BUFFERS) - { - bufferIndex = 0; - } - } + bufferIndex++; + if(bufferIndex >= LINKBUS_NUMBER_OF_TX_MSG_BUFFERS) + { + bufferIndex = 0; + } + } - if(found) - { - return( &tx_buffer[bufferIndex]); - } + if(found) + { + return( &tx_buffer[bufferIndex]); + } - return(null); + return(null); } LinkbusTxBuffer* nextEmptyTxBuffer(void) { - BOOL found = TRUE; - static uint8_t bufferIndex = 0; - uint8_t count = 0; + BOOL found = TRUE; + static uint8_t bufferIndex = 0; + uint8_t count = 0; - while(tx_buffer[bufferIndex][0] != '\0') - { - if(++count >= LINKBUS_NUMBER_OF_TX_MSG_BUFFERS) - { - found = FALSE; - break; - } + while(tx_buffer[bufferIndex][0] != '\0') + { + if(++count >= LINKBUS_NUMBER_OF_TX_MSG_BUFFERS) + { + found = FALSE; + break; + } - bufferIndex++; - if(bufferIndex >= LINKBUS_NUMBER_OF_TX_MSG_BUFFERS) - { - bufferIndex = 0; - } - } + bufferIndex++; + if(bufferIndex >= LINKBUS_NUMBER_OF_TX_MSG_BUFFERS) + { + bufferIndex = 0; + } + } - if(found) - { - return( &tx_buffer[bufferIndex]); - } + if(found) + { + return( &tx_buffer[bufferIndex]); + } - return(null); + return(null); } LinkbusRxBuffer* nextEmptyRxBuffer(void) { - BOOL found = TRUE; - static uint8_t bufferIndex = 0; - uint8_t count = 0; + BOOL found = TRUE; + static uint8_t bufferIndex = 0; + uint8_t count = 0; - while(rx_buffer[bufferIndex].id != MESSAGE_EMPTY) - { - if(++count >= LINKBUS_NUMBER_OF_RX_MSG_BUFFERS) - { - found = FALSE; - break; - } + while(rx_buffer[bufferIndex].id != MESSAGE_EMPTY) + { + if(++count >= LINKBUS_NUMBER_OF_RX_MSG_BUFFERS) + { + found = FALSE; + break; + } - bufferIndex++; - if(bufferIndex >= LINKBUS_NUMBER_OF_RX_MSG_BUFFERS) - { - bufferIndex = 0; - } - } + bufferIndex++; + if(bufferIndex >= LINKBUS_NUMBER_OF_RX_MSG_BUFFERS) + { + bufferIndex = 0; + } + } - if(found) - { - return( &rx_buffer[bufferIndex]); - } + if(found) + { + return( &rx_buffer[bufferIndex]); + } - return(null); + return(null); } LinkbusRxBuffer* nextFullRxBuffer(void) { - BOOL found = TRUE; - static uint8_t bufferIndex = 0; - uint8_t count = 0; + BOOL found = TRUE; + static uint8_t bufferIndex = 0; + uint8_t count = 0; - while(rx_buffer[bufferIndex].id == MESSAGE_EMPTY) - { - if(++count >= LINKBUS_NUMBER_OF_RX_MSG_BUFFERS) - { - found = FALSE; - break; - } + while(rx_buffer[bufferIndex].id == MESSAGE_EMPTY) + { + if(++count >= LINKBUS_NUMBER_OF_RX_MSG_BUFFERS) + { + found = FALSE; + break; + } - bufferIndex++; - if(bufferIndex >= LINKBUS_NUMBER_OF_RX_MSG_BUFFERS) - { - bufferIndex = 0; - } - } + bufferIndex++; + if(bufferIndex >= LINKBUS_NUMBER_OF_RX_MSG_BUFFERS) + { + bufferIndex = 0; + } + } - if(found) - { - return( &rx_buffer[bufferIndex]); - } + if(found) + { + return( &rx_buffer[bufferIndex]); + } - return(null); + return(null); } @@ -169,125 +179,131 @@ LinkbusRxBuffer* nextFullRxBuffer(void) ************************************************************************/ BOOL linkbusTxInProgress(void) { - return(linkbus_tx_active); + return(linkbus_tx_active); } BOOL linkbus_start_tx(void) { - BOOL success = !linkbus_tx_active; + BOOL success = !linkbus_tx_active; - if(success) /* message will be lost if transmit is busy */ - { - linkbus_tx_active = TRUE; - UCSR0B |= (1 << UDRIE0); - } + if(success) /* message will be lost if transmit is busy */ + { + linkbus_tx_active = TRUE; + UCSR0B |= (1 << UDRIE0); + } - return(success); + return(success); } void linkbus_end_tx(void) { - if(linkbus_tx_active) - { - UCSR0B &= ~(1 << UDRIE0); - linkbus_tx_active = FALSE; - } + if(linkbus_tx_active) + { + UCSR0B &= ~(1 << UDRIE0); + linkbus_tx_active = FALSE; + } } void linkbus_reset_rx(void) { - if(UCSR0B & (1 << RXEN0)) /* perform only if rx is currently enabled */ - { - UCSR0B &= ~(1 << RXEN0); + if(UCSR0B & (1 << RXEN0)) /* perform only if rx is currently enabled */ + { + UCSR0B &= ~(1 << RXEN0); /* uint16_t s = sizeof(rx_buffer); // test */ - memset(rx_buffer, 0, sizeof(rx_buffer)); + memset(rx_buffer, 0, sizeof(rx_buffer)); /* if(s) s = 0; // test */ - UCSR0B |= (1 << RXEN0); - } + UCSR0B |= (1 << RXEN0); + } } void linkbus_init(uint32_t baud) { - memset(rx_buffer, 0, sizeof(rx_buffer)); + memset(rx_buffer, 0, sizeof(rx_buffer)); - for(int bufferIndex=0; bufferIndex> 8); - UBRR0L = (uint8_t)myubrr; - /* Enable receiver and transmitter and related interrupts */ - UCSR0B = (1 << RXEN0) | (1 << TXEN0) | (1 << RXCIE0); -/* UCSR0B = (1<> 8); + UBRR0L = (uint8_t)myubrr; + /* Enable receiver and transmitter and related interrupts */ + UCSR0B = (1 << RXEN0) | (1 << TXEN0) | (1 << RXCIE0); +/* UCSR0B = (1< LINKBUS_MAX_MSG_LENGTH) return TRUE; + if(str == NULL) + { + return( TRUE); + } + if(strlen(str) > LINKBUS_MAX_MSG_LENGTH) + { + return( TRUE); + } strncpy(g_tempMsgBuff, str, LINKBUS_MAX_MSG_LENGTH); linkbus_send_text(g_tempMsgBuff); - return FALSE; + return( FALSE); } void lb_send_value(uint16_t value, char* label) @@ -377,3 +402,41 @@ void lb_send_value(uint16_t value, char* label) sprintf(g_tempMsgBuff, "> %s=%d%s", label, value, lineTerm); linkbus_send_text(g_tempMsgBuff); } + +/*********************************************************************** + * lb_send_Help(void) + ************************************************************************/ +void lb_send_Help(void) +{ + if(g_bus_disabled) + { + return; + } + + sprintf(g_tempMsgBuff, "\n*** %s Ver. %s ***", PRODUCT_NAME_LONG, SW_REVISION); + + while(linkbus_send_text(g_tempMsgBuff)) + { + ; + } + while(linkbusTxInProgress()) + { + ; + } + + size_t n = sizeof(textHelp) / sizeof(textHelp[0]); + for(uint8_t i = 0; i < n; i++) + { + while(linkbus_send_text((char*)textHelp[i])) + { + ; + } + while(linkbusTxInProgress()) + { + ; + } + } + + lb_send_NewLine(); +} + diff --git a/linkbus.h b/linkbus.h index dbf4e92..b8c6e76 100644 --- a/linkbus.h +++ b/linkbus.h @@ -35,7 +35,8 @@ #define LINKBUS_MAX_MSG_FIELD_LENGTH 21 #define LINKBUS_MAX_MSG_NUMBER_OF_FIELDS 3 #define LINKBUS_NUMBER_OF_RX_MSG_BUFFERS 2 -#define LINKBUS_NUMBER_OF_TX_MSG_BUFFERS 8 +#define LINKBUS_MAX_TX_MSG_LENGTH 40 +#define LINKBUS_NUMBER_OF_TX_MSG_BUFFERS 10 #define LINKBUS_POWERUP_DELAY_SECONDS 6 @@ -97,21 +98,10 @@ 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_CLOCK = 'T' * 100 + 'I' * 10 + 'M', /* Sets/reads the real-time clock */ - MESSAGE_STARTFINISH = 'S' * 10 + 'F', /* Sets the start and finish times */ - MESSAGE_BAT = 'B' * 100 + 'A' * 10 + 'T', /* Battery charge data */ + MESSAGE_SYNC_ENABLE = 'S' * 100 + 'Y' * 10 + 'N', /* Enable or disable transmitter syncing */ MESSAGE_TEMP = 'T' * 100 + 'E' * 10 + 'M', /* Temperature data */ - MESSAGE_PERM = 'P' * 100 + 'R' * 10 + 'M', /* Saves most settings to EEPROM "perm" */ - MESSAGE_TX_POWER = 'P' * 100 + 'O' * 10 + 'W', /* Sets transmit power level */ - MESSAGE_TX_MOD = 'M' * 100 + 'O' * 10 + 'D', /* Sets 2m modulation format to AM or CW */ -#ifdef DONOTUSE - MESSAGE_DRIVE_LEVEL = 'D' * 100 + 'R' * 10 + 'I', /* Adjust 2m drive level */ -#endif // DONOTUSE MESSAGE_SET_STATION_ID = 'I' * 10 + 'D', /* Sets amateur radio callsign text */ - MESSAGE_SET_PATTERN = 'P' * 10 + 'A', /* Sets unique transmit pattern */ - MESSAGE_CODE_SPEED = 'S' * 100 + 'P' * 10 + 'D', /* Sets id and pattern code speeds */ - MESSAGE_ESP_COMM = 'E' * 100 + 'S' * 10 + 'P', /* Communications with ESP8266 controller */ - MESSAGE_GO = 'G' * 10 + 'O', /* Start transmitting now without delay */ + MESSAGE_GO = 'G' * 10 + 'O', /* Synchronizes clock */ /* UTILITY MESSAGES */ MESSAGE_RESET = 'R' * 100 + 'S' * 10 + 'T', /* Processor reset */ @@ -120,14 +110,6 @@ typedef enum INVALID_MESSAGE = UINT16_MAX /* This value must never overlap a valid message ID */ } LBMessageID; -#define MESSAGE_CLOCK_LABEL "TIM" -#define MESSAGE_ESP_LABEL "ESP" -#define MESSAGE_ERRORCODE_LABEL "EC" -#define MESSAGE_STATUSCODE_LABEL "SC" -#define MESSAGE_BAND_LABEL "BND" -#define MESSAGE_TX_POWER_LABEL "POW" -#define MESSAGE_ACK "!ACK;" - typedef enum { LINKBUS_MSG_UNKNOWN = 0, @@ -161,7 +143,7 @@ typedef enum TRANSMITTER_ID = 3 } DeviceID; -typedef char LinkbusTxBuffer[LINKBUS_MAX_MSG_LENGTH]; +typedef char LinkbusTxBuffer[LINKBUS_MAX_TX_MSG_LENGTH]; typedef struct { @@ -263,4 +245,8 @@ BOOL lb_send_string(char* str); */ void lb_send_value(uint16_t value, char* label); +/** + */ +void lb_send_Help(void); + #endif /* LINKBUS_H_ */ From b156b5fa2e38702f53855bbf7874752a458ba21c Mon Sep 17 00:00:00 2001 From: DigitalConfections Date: Tue, 26 May 2020 08:50:47 -0400 Subject: [PATCH 5/6] New Folder Created a folder to hold the Arduino script. This should allow the project to build under Arduino IDE without the user needing to create a new folder. --- .../Arduino-microfox.ino | 0 LICENSE => Arduino-microfox/LICENSE | 0 README.md => Arduino-microfox/README.md | 0 defs.h => Arduino-microfox/defs.h | 670 ++++++------- linkbus.cpp => Arduino-microfox/linkbus.cpp | 884 +++++++++--------- linkbus.h => Arduino-microfox/linkbus.h | 504 +++++----- 6 files changed, 1029 insertions(+), 1029 deletions(-) rename Arduino-microfox.ino => Arduino-microfox/Arduino-microfox.ino (100%) rename LICENSE => Arduino-microfox/LICENSE (100%) rename README.md => Arduino-microfox/README.md (100%) rename defs.h => Arduino-microfox/defs.h (96%) rename linkbus.cpp => Arduino-microfox/linkbus.cpp (95%) rename linkbus.h => Arduino-microfox/linkbus.h (96%) diff --git a/Arduino-microfox.ino b/Arduino-microfox/Arduino-microfox.ino similarity index 100% rename from Arduino-microfox.ino rename to Arduino-microfox/Arduino-microfox.ino diff --git a/LICENSE b/Arduino-microfox/LICENSE similarity index 100% rename from LICENSE rename to Arduino-microfox/LICENSE diff --git a/README.md b/Arduino-microfox/README.md similarity index 100% rename from README.md rename to Arduino-microfox/README.md diff --git a/defs.h b/Arduino-microfox/defs.h similarity index 96% rename from defs.h rename to Arduino-microfox/defs.h index f639927..93a1950 100644 --- a/defs.h +++ b/Arduino-microfox/defs.h @@ -1,335 +1,335 @@ - -/********************************************************************************************** -* Copyright � 2017 Digital Confections LLC -* -* Permission is hereby granted, free of charge, to any person obtaining a copy of -* this software and associated documentation files (the "Software"), to deal in the -* Software without restriction, including without limitation the rights to use, copy, -* modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, -* and to permit persons to whom the Software is furnished to do so, subject to the -* following conditions: -* -* The above copyright notice and this permission notice shall be included in all -* copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, -* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR -* PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE -* FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -* DEALINGS IN THE SOFTWARE. -* -**********************************************************************************************/ - -#ifndef DEFS_H -#define DEFS_H - -#include - -/* #define F_CPU 16000000UL / * gets declared in makefile * / */ - - -/****************************************************** - * Set the text that gets displayed to the user */ -#define SW_REVISION "0.1" - -//#define TRANQUILIZE_WATCHDOG - -#define PRODUCT_NAME_SHORT "ARDF Tx" -#define PRODUCT_NAME_LONG "WB8WFK ARDF Transmitter" - -/*******************************************************/ - -#ifndef uint16_t_defined -#define uint16_t_defined -typedef unsigned int uint16_t; -#endif - -#ifndef uint32_t_defined -#define uint32_t_defined -typedef unsigned long uint32_t; -#endif - -#ifndef unit8_t_defined -#define unit8_t_defined -typedef unsigned char uint8_t; -#endif - -#ifndef null -#define null 0 -#endif - -#ifdef INCLUDE_DAC081C085_SUPPORT - #define PA_DAC DAC081C_I2C_SLAVE_ADDR_A0 - #define AM_DAC DAC081C_I2C_SLAVE_ADDR_A1 - #define BIAS_DAC DAC081C_I2C_SLAVE_ADDR_A2 -#endif - -typedef enum { -// TX1 = 0xA4, -// TX2 = 0xA3, -// TX3 = 0xA2, -// TX4 = 0xA1, - TX5 = 0xA0 - } Tx_t; - -/*******************************************************/ -/* Error Codes */ -/*******************************************************/ -typedef enum { - ERROR_CODE_NO_ERROR = 0x00, - ERROR_CODE_REPORT_NO_ERROR = 0x01, - ERROR_CODE_2M_BIAS_SM_NOT_READY = 0xC6, - ERROR_CODE_EVENT_STATION_ID_ERROR = 0xC7, - ERROR_CODE_EVENT_PATTERN_CODE_SPEED_NOT_SPECIFIED = 0xC8, - ERROR_CODE_EVENT_PATTERN_NOT_SPECIFIED = 0xC9, - ERROR_CODE_EVENT_TIMING_ERROR = 0xCA, - ERROR_CODE_EVENT_MISSING_TRANSMIT_DURATION = 0xCB, - ERROR_CODE_EVENT_MISSING_START_TIME = 0xCC, - ERROR_CODE_EVENT_NOT_CONFIGURED = 0xCD, - ERROR_CODE_ILLEGAL_COMMAND_RCVD = 0xCE, - ERROR_CODE_SW_LOGIC_ERROR = 0xCF, - ERROR_CODE_POWER_LEVEL_NOT_SUPPORTED = 0xF5, - ERROR_CODE_NO_ANTENNA_PREVENTS_POWER_SETTING = 0xF6, - ERROR_CODE_NO_ANTENNA_FOR_BAND = 0xF7, - ERROR_CODE_WD_TIMEOUT = 0xF8, - ERROR_CODE_SUPPLY_VOLTAGE_ERROR = 0xF9, - ERROR_CODE_BUCK_REG_OUTOFSPEC = 0xFA, - ERROR_CODE_CLKGEN_NONRESPONSIVE = 0xFB, - ERROR_CODE_RTC_NONRESPONSIVE = 0xFC, - ERROR_CODE_DAC3_NONRESPONSIVE = 0xFD, - ERROR_CODE_DAC2_NONRESPONSIVE = 0xFE, - ERROR_CODE_DAC1_NONRESPONSIVE = 0xFF - } EC; - -/*******************************************************/ -/* Status Codes */ -/*******************************************************/ -typedef enum { - STATUS_CODE_IDLE = 0x00, - STATUS_CODE_REPORT_IDLE = 0x01, - STATUS_CODE_NO_ANT_ATTACHED = 0xE9, - STATUS_CODE_2M_ANT_ATTACHED = 0xEA, - STATUS_CODE_80M_ANT_ATTACHED = 0xEB, - STATUS_CODE_RECEIVING_EVENT_DATA = 0xEC, - STATUS_CODE_RETURNED_FROM_SLEEP = 0xED, - STATUS_CODE_BEGINNING_XMSN_THIS_CYCLE = 0xEE, - STATUS_CODE_SENDING_ID = 0xEF, - STATUS_CODE_EVENT_NEVER_ENDS = 0xFB, - STATUS_CODE_EVENT_FINISHED = 0xFC, - STATUS_CODE_EVENT_STARTED_NOW_TRANSMITTING = 0xFD, - STATUS_CODE_EVENT_STARTED_WAITING_FOR_TIME_SLOT = 0xFE, - STATUS_CODE_WAITING_FOR_EVENT_START = 0xFF - } SC; - -/*******************************************************/ -/******************************************************* -* ADC Scale Factors */ -/* Battery voltage should be read when +12V supply is enabled and all transmitters are fully powered off */ -#define ADC_REF_VOLTAGE_mV 1100UL - -#define ADC_MAX_VOLTAGE_MV 4200L /* maximum voltage the ADC can read */ -#define BATTERY_VOLTAGE_MAX_MV 4200L /* voltage at which the battery is considered to be fully charged */ -#define BATTERY_DROP 320L /* voltage drop between the battery terminals and the ADC input while powering the ESP8266 */ -#define BATTERY_DROP_OFFSET (BATTERY_DROP * 1023L) -#define VBAT(x) (BATTERY_DROP + (x * ADC_MAX_VOLTAGE_MV) / 1023L) -#define BATTERY_PERCENTAGE(x, y) ( ( 100L * ((x * ADC_MAX_VOLTAGE_MV + BATTERY_DROP_OFFSET) - (1023L * y)) ) / ((BATTERY_VOLTAGE_MAX_MV - y) * 1023L)) - -#define SUPPLY_VOLTAGE_MAX_MV 14100L -#define VSUPPLY(x)((x * SUPPLY_VOLTAGE_MAX_MV) / 1023L) - -#define PA_VOLTAGE_MAX_MV 14100L -#define VPA(x)((x * PA_VOLTAGE_MAX_MV) / 1023L) - -typedef uint16_t BatteryLevel; /* in milliVolts */ - -#define VOLTS_5 (((5000L - BATTERY_DROP) * 1023L) / BATTERY_VOLTAGE_MAX_MV) -#define VOLTS_3_19 (((3190L - BATTERY_DROP) * 1023L) / BATTERY_VOLTAGE_MAX_MV) -#define VOLTS_3_0 (((3000L - BATTERY_DROP) * 1023L) / BATTERY_VOLTAGE_MAX_MV) -#define VOLTS_2_4 (((2400L - BATTERY_DROP) * 1023L) / BATTERY_VOLTAGE_MAX_MV) - -#define POWER_OFF_VOLT_THRESH_MV VOLTS_2_4 /* 2.4 V = 2400 mV */ -#define POWER_ON_VOLT_THRESH_MV VOLTS_3_0 /* 3.0 V = 3000 mV */ - -#define ANTENNA_DETECT_THRESH 20 -#define ANTENNA_DETECT_DEBOUNCE 50 - -#define NUMBER_OF_ESSENTIAL_EVENT_PARAMETERS 14 - - -/*******************************************************/ - -#ifndef SELECTIVELY_DISABLE_OPTIMIZATION - #define SELECTIVELY_DISABLE_OPTIMIZATION -#endif - -/****************************************************** - * EEPROM definitions */ -#define EEPROM_INITIALIZED_FLAG 0xAD -#define EEPROM_UNINITIALIZED 0x00 - -#define EEPROM_STATION_ID_DEFAULT "FOXBOX" -#define EEPROM_PATTERN_TEXT_DEFAULT "PARIS|" - -#define EEPROM_START_TIME_DEFAULT 0 -#define EEPROM_FINISH_TIME_DEFAULT 0 -#define EEPROM_EVENT_ENABLED_DEFAULT FALSE -#define EEPROM_ID_CODE_SPEED_DEFAULT 20 -#define EEPROM_PATTERN_CODE_SPEED_DEFAULT 8 -#define EEPROM_ON_AIR_TIME_DEFAULT 60 -#define EEPROM_OFF_AIR_TIME_DEFAULT 240 -#define EEPROM_INTRA_CYCLE_DELAY_TIME_DEFAULT 0 -#define EEPROM_ID_TIME_INTERVAL_DEFAULT 300 -#define EEPROM_CLOCK_CALIBRATION_DEFAULT 15629 -#define EEPROM_OVERRIDE_DIP_SW_DEFAULT 0 -#define EEPROM_ENABLE_LEDS_DEFAULT 1 -#define EEPROM_ENABLE_SYNC_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 - -#ifndef Frequency_Hz - typedef unsigned long Frequency_Hz; -#endif - -#ifndef UINT16_MAX -#define UINT16_MAX __INT16_MAX__ -#endif - -#define ON 1 -#define OFF 0 -#define TOGGLE 2 - -#define UNDETERMINED 3 - -#define MIN(A,B) ({ __typeof__(A) __a = (A); __typeof__(B) __b = (B); __a < __b ? __a : __b; }) -#define MAX(A,B) ({ __typeof__(A) __a = (A); __typeof__(B) __b = (B); __a < __b ? __b : __a; }) - -#define CLAMP(low, x, high) ({\ - __typeof__(x) __x = (x); \ - __typeof__(low) __low = (low);\ - __typeof__(high) __high = (high);\ - __x > __high ? __high : (__x < __low ? __low : __x);\ - }) - -#define MAX_TIME 4294967295L -#define MAX_UINT16 65535 -#define MAX_INT16 32767 - -typedef enum -{ - DOWN = -1, - NOCHANGE = 0, - UP = 1, - SETTOVALUE -} IncrType; - -typedef enum -{ - ANT_CONNECTION_UNDETERMINED, - ANT_ALL_DISCONNECTED, - ANT_2M_CONNECTED, - ANT_80M_CONNECTED, - ANT_2M_AND_80M_CONNECTED -} AntConnType; - -typedef enum -{ - POWER_UP, - POWER_SLEEP -} InitActionType; - -#define QUAD_MASK 0xC0 -#define QUAD_A 7 -#define QUAD_B 6 - -#define MAX_TONE_VOLUME_SETTING 15 -#define TONE_POT_VAL(x) (255 - (x*17)) -#define MAX_MAIN_VOLUME_SETTING 15 - -#define POWER_OFF_DELAY 5000 -#define BACKLIGHT_OFF_DELAY 5000 -#define BACKLIGHT_ALWAYS_ON 65535 -#define HEADPHONE_REMOVED_DELAY 100 -#define POWERUP_LOW_VOLTAGE_DELAY 900 /* A short delay at first power up before declaring battery is too low */ -#define LOW_VOLTAGE_DELAY 9000 /* A longer delay if the receiver has been running and the battery starts to sag */ -#define CURSOR_EXPIRATION_DELAY 5000 /* Keep cursor displayed this long without user action */ -#define LONG_PRESS_TICK_COUNT 1200 /* Press a button for this many ticks in order to access a long-press function */ - -#define SEND_ID_DELAY 4100 - -/* Periodic TIMER2 interrupt timing definitions */ -#define TIMER2_57HZ 10 -#define TIMER2_20HZ 49 -#define TIMER2_5_8HZ 100 -#define TIMER2_0_5HZ 1000 - -#define BEEP_SHORT 100 -#define BEEP_LONG 65535 - -/****************************************************** - * UI Hardware-related definitions */ - -typedef enum -{ - FrequencyFormat, - HourMinuteSecondFormat, - HourMinuteSecondDateFormat -} TextFormat; - -#define DISPLAY_WIDTH_STRING_SIZE (NUMBER_OF_LCD_COLS + 1) - -typedef enum batteryType -{ - BATTERY_9V, - BATTERY_4r2V, - BATTERY_EXTERNAL, - BATTERY_UNKNOWN -} BatteryType; - -typedef enum -{ - Minutes_Seconds, /* minutes up to 59 */ - Hours_Minutes_Seconds, /* hours up to 23 */ - Day_Month_Year_Hours_Minutes_Seconds, /* Year up to 99 */ - Minutes_Seconds_Elapsed, /* minutes up to 99 */ - Time_Format_Not_Specified -} TimeFormat; - -#define NO_TIME_SPECIFIED (-1) - -#define SecondsFromHours(hours) ((hours) * 3600) -#define SecondsFromMinutes(min) ((min) * 60) - -typedef enum -{ - PATTERN_TEXT, - STATION_ID -} TextIndex; - -#endif /* DEFS_H */ + +/********************************************************************************************** +* Copyright � 2017 Digital Confections LLC +* +* Permission is hereby granted, free of charge, to any person obtaining a copy of +* this software and associated documentation files (the "Software"), to deal in the +* Software without restriction, including without limitation the rights to use, copy, +* modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, +* and to permit persons to whom the Software is furnished to do so, subject to the +* following conditions: +* +* The above copyright notice and this permission notice shall be included in all +* copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +* PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +* FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +* DEALINGS IN THE SOFTWARE. +* +**********************************************************************************************/ + +#ifndef DEFS_H +#define DEFS_H + +#include + +/* #define F_CPU 16000000UL / * gets declared in makefile * / */ + + +/****************************************************** + * Set the text that gets displayed to the user */ +#define SW_REVISION "0.1" + +//#define TRANQUILIZE_WATCHDOG + +#define PRODUCT_NAME_SHORT "ARDF Tx" +#define PRODUCT_NAME_LONG "WB8WFK ARDF Transmitter" + +/*******************************************************/ + +#ifndef uint16_t_defined +#define uint16_t_defined +typedef unsigned int uint16_t; +#endif + +#ifndef uint32_t_defined +#define uint32_t_defined +typedef unsigned long uint32_t; +#endif + +#ifndef unit8_t_defined +#define unit8_t_defined +typedef unsigned char uint8_t; +#endif + +#ifndef null +#define null 0 +#endif + +#ifdef INCLUDE_DAC081C085_SUPPORT + #define PA_DAC DAC081C_I2C_SLAVE_ADDR_A0 + #define AM_DAC DAC081C_I2C_SLAVE_ADDR_A1 + #define BIAS_DAC DAC081C_I2C_SLAVE_ADDR_A2 +#endif + +typedef enum { +// TX1 = 0xA4, +// TX2 = 0xA3, +// TX3 = 0xA2, +// TX4 = 0xA1, + TX5 = 0xA0 + } Tx_t; + +/*******************************************************/ +/* Error Codes */ +/*******************************************************/ +typedef enum { + ERROR_CODE_NO_ERROR = 0x00, + ERROR_CODE_REPORT_NO_ERROR = 0x01, + ERROR_CODE_2M_BIAS_SM_NOT_READY = 0xC6, + ERROR_CODE_EVENT_STATION_ID_ERROR = 0xC7, + ERROR_CODE_EVENT_PATTERN_CODE_SPEED_NOT_SPECIFIED = 0xC8, + ERROR_CODE_EVENT_PATTERN_NOT_SPECIFIED = 0xC9, + ERROR_CODE_EVENT_TIMING_ERROR = 0xCA, + ERROR_CODE_EVENT_MISSING_TRANSMIT_DURATION = 0xCB, + ERROR_CODE_EVENT_MISSING_START_TIME = 0xCC, + ERROR_CODE_EVENT_NOT_CONFIGURED = 0xCD, + ERROR_CODE_ILLEGAL_COMMAND_RCVD = 0xCE, + ERROR_CODE_SW_LOGIC_ERROR = 0xCF, + ERROR_CODE_POWER_LEVEL_NOT_SUPPORTED = 0xF5, + ERROR_CODE_NO_ANTENNA_PREVENTS_POWER_SETTING = 0xF6, + ERROR_CODE_NO_ANTENNA_FOR_BAND = 0xF7, + ERROR_CODE_WD_TIMEOUT = 0xF8, + ERROR_CODE_SUPPLY_VOLTAGE_ERROR = 0xF9, + ERROR_CODE_BUCK_REG_OUTOFSPEC = 0xFA, + ERROR_CODE_CLKGEN_NONRESPONSIVE = 0xFB, + ERROR_CODE_RTC_NONRESPONSIVE = 0xFC, + ERROR_CODE_DAC3_NONRESPONSIVE = 0xFD, + ERROR_CODE_DAC2_NONRESPONSIVE = 0xFE, + ERROR_CODE_DAC1_NONRESPONSIVE = 0xFF + } EC; + +/*******************************************************/ +/* Status Codes */ +/*******************************************************/ +typedef enum { + STATUS_CODE_IDLE = 0x00, + STATUS_CODE_REPORT_IDLE = 0x01, + STATUS_CODE_NO_ANT_ATTACHED = 0xE9, + STATUS_CODE_2M_ANT_ATTACHED = 0xEA, + STATUS_CODE_80M_ANT_ATTACHED = 0xEB, + STATUS_CODE_RECEIVING_EVENT_DATA = 0xEC, + STATUS_CODE_RETURNED_FROM_SLEEP = 0xED, + STATUS_CODE_BEGINNING_XMSN_THIS_CYCLE = 0xEE, + STATUS_CODE_SENDING_ID = 0xEF, + STATUS_CODE_EVENT_NEVER_ENDS = 0xFB, + STATUS_CODE_EVENT_FINISHED = 0xFC, + STATUS_CODE_EVENT_STARTED_NOW_TRANSMITTING = 0xFD, + STATUS_CODE_EVENT_STARTED_WAITING_FOR_TIME_SLOT = 0xFE, + STATUS_CODE_WAITING_FOR_EVENT_START = 0xFF + } SC; + +/*******************************************************/ +/******************************************************* +* ADC Scale Factors */ +/* Battery voltage should be read when +12V supply is enabled and all transmitters are fully powered off */ +#define ADC_REF_VOLTAGE_mV 1100UL + +#define ADC_MAX_VOLTAGE_MV 4200L /* maximum voltage the ADC can read */ +#define BATTERY_VOLTAGE_MAX_MV 4200L /* voltage at which the battery is considered to be fully charged */ +#define BATTERY_DROP 320L /* voltage drop between the battery terminals and the ADC input while powering the ESP8266 */ +#define BATTERY_DROP_OFFSET (BATTERY_DROP * 1023L) +#define VBAT(x) (BATTERY_DROP + (x * ADC_MAX_VOLTAGE_MV) / 1023L) +#define BATTERY_PERCENTAGE(x, y) ( ( 100L * ((x * ADC_MAX_VOLTAGE_MV + BATTERY_DROP_OFFSET) - (1023L * y)) ) / ((BATTERY_VOLTAGE_MAX_MV - y) * 1023L)) + +#define SUPPLY_VOLTAGE_MAX_MV 14100L +#define VSUPPLY(x)((x * SUPPLY_VOLTAGE_MAX_MV) / 1023L) + +#define PA_VOLTAGE_MAX_MV 14100L +#define VPA(x)((x * PA_VOLTAGE_MAX_MV) / 1023L) + +typedef uint16_t BatteryLevel; /* in milliVolts */ + +#define VOLTS_5 (((5000L - BATTERY_DROP) * 1023L) / BATTERY_VOLTAGE_MAX_MV) +#define VOLTS_3_19 (((3190L - BATTERY_DROP) * 1023L) / BATTERY_VOLTAGE_MAX_MV) +#define VOLTS_3_0 (((3000L - BATTERY_DROP) * 1023L) / BATTERY_VOLTAGE_MAX_MV) +#define VOLTS_2_4 (((2400L - BATTERY_DROP) * 1023L) / BATTERY_VOLTAGE_MAX_MV) + +#define POWER_OFF_VOLT_THRESH_MV VOLTS_2_4 /* 2.4 V = 2400 mV */ +#define POWER_ON_VOLT_THRESH_MV VOLTS_3_0 /* 3.0 V = 3000 mV */ + +#define ANTENNA_DETECT_THRESH 20 +#define ANTENNA_DETECT_DEBOUNCE 50 + +#define NUMBER_OF_ESSENTIAL_EVENT_PARAMETERS 14 + + +/*******************************************************/ + +#ifndef SELECTIVELY_DISABLE_OPTIMIZATION + #define SELECTIVELY_DISABLE_OPTIMIZATION +#endif + +/****************************************************** + * EEPROM definitions */ +#define EEPROM_INITIALIZED_FLAG 0xAD +#define EEPROM_UNINITIALIZED 0x00 + +#define EEPROM_STATION_ID_DEFAULT "FOXBOX" +#define EEPROM_PATTERN_TEXT_DEFAULT "PARIS|" + +#define EEPROM_START_TIME_DEFAULT 0 +#define EEPROM_FINISH_TIME_DEFAULT 0 +#define EEPROM_EVENT_ENABLED_DEFAULT FALSE +#define EEPROM_ID_CODE_SPEED_DEFAULT 20 +#define EEPROM_PATTERN_CODE_SPEED_DEFAULT 8 +#define EEPROM_ON_AIR_TIME_DEFAULT 60 +#define EEPROM_OFF_AIR_TIME_DEFAULT 240 +#define EEPROM_INTRA_CYCLE_DELAY_TIME_DEFAULT 0 +#define EEPROM_ID_TIME_INTERVAL_DEFAULT 300 +#define EEPROM_CLOCK_CALIBRATION_DEFAULT 15629 +#define EEPROM_OVERRIDE_DIP_SW_DEFAULT 0 +#define EEPROM_ENABLE_LEDS_DEFAULT 1 +#define EEPROM_ENABLE_SYNC_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 + +#ifndef Frequency_Hz + typedef unsigned long Frequency_Hz; +#endif + +#ifndef UINT16_MAX +#define UINT16_MAX __INT16_MAX__ +#endif + +#define ON 1 +#define OFF 0 +#define TOGGLE 2 + +#define UNDETERMINED 3 + +#define MIN(A,B) ({ __typeof__(A) __a = (A); __typeof__(B) __b = (B); __a < __b ? __a : __b; }) +#define MAX(A,B) ({ __typeof__(A) __a = (A); __typeof__(B) __b = (B); __a < __b ? __b : __a; }) + +#define CLAMP(low, x, high) ({\ + __typeof__(x) __x = (x); \ + __typeof__(low) __low = (low);\ + __typeof__(high) __high = (high);\ + __x > __high ? __high : (__x < __low ? __low : __x);\ + }) + +#define MAX_TIME 4294967295L +#define MAX_UINT16 65535 +#define MAX_INT16 32767 + +typedef enum +{ + DOWN = -1, + NOCHANGE = 0, + UP = 1, + SETTOVALUE +} IncrType; + +typedef enum +{ + ANT_CONNECTION_UNDETERMINED, + ANT_ALL_DISCONNECTED, + ANT_2M_CONNECTED, + ANT_80M_CONNECTED, + ANT_2M_AND_80M_CONNECTED +} AntConnType; + +typedef enum +{ + POWER_UP, + POWER_SLEEP +} InitActionType; + +#define QUAD_MASK 0xC0 +#define QUAD_A 7 +#define QUAD_B 6 + +#define MAX_TONE_VOLUME_SETTING 15 +#define TONE_POT_VAL(x) (255 - (x*17)) +#define MAX_MAIN_VOLUME_SETTING 15 + +#define POWER_OFF_DELAY 5000 +#define BACKLIGHT_OFF_DELAY 5000 +#define BACKLIGHT_ALWAYS_ON 65535 +#define HEADPHONE_REMOVED_DELAY 100 +#define POWERUP_LOW_VOLTAGE_DELAY 900 /* A short delay at first power up before declaring battery is too low */ +#define LOW_VOLTAGE_DELAY 9000 /* A longer delay if the receiver has been running and the battery starts to sag */ +#define CURSOR_EXPIRATION_DELAY 5000 /* Keep cursor displayed this long without user action */ +#define LONG_PRESS_TICK_COUNT 1200 /* Press a button for this many ticks in order to access a long-press function */ + +#define SEND_ID_DELAY 4100 + +/* Periodic TIMER2 interrupt timing definitions */ +#define TIMER2_57HZ 10 +#define TIMER2_20HZ 49 +#define TIMER2_5_8HZ 100 +#define TIMER2_0_5HZ 1000 + +#define BEEP_SHORT 100 +#define BEEP_LONG 65535 + +/****************************************************** + * UI Hardware-related definitions */ + +typedef enum +{ + FrequencyFormat, + HourMinuteSecondFormat, + HourMinuteSecondDateFormat +} TextFormat; + +#define DISPLAY_WIDTH_STRING_SIZE (NUMBER_OF_LCD_COLS + 1) + +typedef enum batteryType +{ + BATTERY_9V, + BATTERY_4r2V, + BATTERY_EXTERNAL, + BATTERY_UNKNOWN +} BatteryType; + +typedef enum +{ + Minutes_Seconds, /* minutes up to 59 */ + Hours_Minutes_Seconds, /* hours up to 23 */ + Day_Month_Year_Hours_Minutes_Seconds, /* Year up to 99 */ + Minutes_Seconds_Elapsed, /* minutes up to 99 */ + Time_Format_Not_Specified +} TimeFormat; + +#define NO_TIME_SPECIFIED (-1) + +#define SecondsFromHours(hours) ((hours) * 3600) +#define SecondsFromMinutes(min) ((min) * 60) + +typedef enum +{ + PATTERN_TEXT, + STATION_ID +} TextIndex; + +#endif /* DEFS_H */ diff --git a/linkbus.cpp b/Arduino-microfox/linkbus.cpp similarity index 95% rename from linkbus.cpp rename to Arduino-microfox/linkbus.cpp index d1b2fc8..3008a40 100644 --- a/linkbus.cpp +++ b/Arduino-microfox/linkbus.cpp @@ -1,442 +1,442 @@ -/********************************************************************************************** - * Copyright © 2017 Digital Confections LLC - * - * Permission is hereby granted, free of charge, to any person obtaining a copy of - * this software and associated documentation files (the "Software"), to deal in the - * Software without restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, subject to the - * following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, - * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE - * FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - ********************************************************************************************** - * linkbus.c - * - */ - -#include "linkbus.h" -#include "defs.h" -//#include "util.h" -//#include -//#include -//#include - -/* Global Variables */ -static volatile BOOL g_bus_disabled = TRUE; -static const char crlf[] = "\n"; -static char lineTerm[8] = "\n"; -static const char textPrompt[] = "> "; - -static const char textHelp[][LINKBUS_MAX_TX_MSG_LENGTH] = { "\nCommands:\n", - " CAL - Calibrate\n", - " DIP - Override DIP\n", - " FAC - Factory reset\n", - " GO - Sync clock\n", - " ID - Set callsign\n", - " LED - LED on/off\n", - " RST - Reset\n", - " SYN - Sync on/off\n", - " VER - S/W version\n" }; - -static char g_tempMsgBuff[LINKBUS_MAX_MSG_LENGTH]; - -/* Local function prototypes */ -BOOL linkbus_start_tx(void); - -/* Module global variables */ -static volatile BOOL linkbus_tx_active = FALSE; /* volatile is required to ensure optimizer handles this properly */ -static LinkbusTxBuffer tx_buffer[LINKBUS_NUMBER_OF_TX_MSG_BUFFERS]; -static LinkbusRxBuffer rx_buffer[LINKBUS_NUMBER_OF_RX_MSG_BUFFERS]; - -LinkbusTxBuffer* nextFullTxBuffer(void) -{ - BOOL found = TRUE; - static uint8_t bufferIndex = 0; - uint8_t count = 0; - - while(tx_buffer[bufferIndex][0] == '\0') - { - if(++count >= LINKBUS_NUMBER_OF_TX_MSG_BUFFERS) - { - found = FALSE; - break; - } - - bufferIndex++; - if(bufferIndex >= LINKBUS_NUMBER_OF_TX_MSG_BUFFERS) - { - bufferIndex = 0; - } - } - - if(found) - { - return( &tx_buffer[bufferIndex]); - } - - return(null); -} - -LinkbusTxBuffer* nextEmptyTxBuffer(void) -{ - BOOL found = TRUE; - static uint8_t bufferIndex = 0; - uint8_t count = 0; - - while(tx_buffer[bufferIndex][0] != '\0') - { - if(++count >= LINKBUS_NUMBER_OF_TX_MSG_BUFFERS) - { - found = FALSE; - break; - } - - bufferIndex++; - if(bufferIndex >= LINKBUS_NUMBER_OF_TX_MSG_BUFFERS) - { - bufferIndex = 0; - } - } - - if(found) - { - return( &tx_buffer[bufferIndex]); - } - - return(null); -} - -LinkbusRxBuffer* nextEmptyRxBuffer(void) -{ - BOOL found = TRUE; - static uint8_t bufferIndex = 0; - uint8_t count = 0; - - while(rx_buffer[bufferIndex].id != MESSAGE_EMPTY) - { - if(++count >= LINKBUS_NUMBER_OF_RX_MSG_BUFFERS) - { - found = FALSE; - break; - } - - bufferIndex++; - if(bufferIndex >= LINKBUS_NUMBER_OF_RX_MSG_BUFFERS) - { - bufferIndex = 0; - } - } - - if(found) - { - return( &rx_buffer[bufferIndex]); - } - - return(null); -} - -LinkbusRxBuffer* nextFullRxBuffer(void) -{ - BOOL found = TRUE; - static uint8_t bufferIndex = 0; - uint8_t count = 0; - - while(rx_buffer[bufferIndex].id == MESSAGE_EMPTY) - { - if(++count >= LINKBUS_NUMBER_OF_RX_MSG_BUFFERS) - { - found = FALSE; - break; - } - - bufferIndex++; - if(bufferIndex >= LINKBUS_NUMBER_OF_RX_MSG_BUFFERS) - { - bufferIndex = 0; - } - } - - if(found) - { - return( &rx_buffer[bufferIndex]); - } - - return(null); -} - - -/*********************************************************************** - * linkbusTxInProgress(void) - ************************************************************************/ -BOOL linkbusTxInProgress(void) -{ - return(linkbus_tx_active); -} - -BOOL linkbus_start_tx(void) -{ - BOOL success = !linkbus_tx_active; - - if(success) /* message will be lost if transmit is busy */ - { - linkbus_tx_active = TRUE; - UCSR0B |= (1 << UDRIE0); - } - - return(success); -} - -void linkbus_end_tx(void) -{ - if(linkbus_tx_active) - { - UCSR0B &= ~(1 << UDRIE0); - linkbus_tx_active = FALSE; - } -} - -void linkbus_reset_rx(void) -{ - if(UCSR0B & (1 << RXEN0)) /* perform only if rx is currently enabled */ - { - UCSR0B &= ~(1 << RXEN0); -/* uint16_t s = sizeof(rx_buffer); // test */ - memset(rx_buffer, 0, sizeof(rx_buffer)); -/* if(s) s = 0; // test */ - UCSR0B |= (1 << RXEN0); - } -} - -void linkbus_init(uint32_t baud) -{ - memset(rx_buffer, 0, sizeof(rx_buffer)); - - for(int bufferIndex = 0; bufferIndex < LINKBUS_NUMBER_OF_TX_MSG_BUFFERS; bufferIndex++) - { - tx_buffer[bufferIndex][0] = '\0'; - } - - /*Set baud rate */ - uint16_t myubrr = MYUBRR(baud); - UBRR0H = (uint8_t)(myubrr >> 8); - UBRR0L = (uint8_t)myubrr; - /* Enable receiver and transmitter and related interrupts */ - UCSR0B = (1 << RXEN0) | (1 << TXEN0) | (1 << RXCIE0); -/* UCSR0B = (1< LINKBUS_MAX_MSG_LENGTH) - { - return( TRUE); - } - strncpy(g_tempMsgBuff, str, LINKBUS_MAX_MSG_LENGTH); - linkbus_send_text(g_tempMsgBuff); - return( FALSE); -} - -void lb_send_value(uint16_t value, char* label) -{ - sprintf(g_tempMsgBuff, "> %s=%d%s", label, value, lineTerm); - linkbus_send_text(g_tempMsgBuff); -} - -/*********************************************************************** - * lb_send_Help(void) - ************************************************************************/ -void lb_send_Help(void) -{ - if(g_bus_disabled) - { - return; - } - - sprintf(g_tempMsgBuff, "\n*** %s Ver. %s ***", PRODUCT_NAME_LONG, SW_REVISION); - - while(linkbus_send_text(g_tempMsgBuff)) - { - ; - } - while(linkbusTxInProgress()) - { - ; - } - - size_t n = sizeof(textHelp) / sizeof(textHelp[0]); - for(uint8_t i = 0; i < n; i++) - { - while(linkbus_send_text((char*)textHelp[i])) - { - ; - } - while(linkbusTxInProgress()) - { - ; - } - } - - lb_send_NewLine(); -} - +/********************************************************************************************** + * Copyright © 2017 Digital Confections LLC + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in the + * Software without restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the + * following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR + * PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE + * FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + ********************************************************************************************** + * linkbus.c + * + */ + +#include "linkbus.h" +#include "defs.h" +//#include "util.h" +//#include +//#include +//#include + +/* Global Variables */ +static volatile BOOL g_bus_disabled = TRUE; +static const char crlf[] = "\n"; +static char lineTerm[8] = "\n"; +static const char textPrompt[] = "> "; + +static const char textHelp[][LINKBUS_MAX_TX_MSG_LENGTH] = { "\nCommands:\n", + " CAL - Calibrate\n", + " DIP - Override DIP\n", + " FAC - Factory reset\n", + " GO - Sync clock\n", + " ID - Set callsign\n", + " LED - LED on/off\n", + " RST - Reset\n", + " SYN - Sync on/off\n", + " VER - S/W version\n" }; + +static char g_tempMsgBuff[LINKBUS_MAX_MSG_LENGTH]; + +/* Local function prototypes */ +BOOL linkbus_start_tx(void); + +/* Module global variables */ +static volatile BOOL linkbus_tx_active = FALSE; /* volatile is required to ensure optimizer handles this properly */ +static LinkbusTxBuffer tx_buffer[LINKBUS_NUMBER_OF_TX_MSG_BUFFERS]; +static LinkbusRxBuffer rx_buffer[LINKBUS_NUMBER_OF_RX_MSG_BUFFERS]; + +LinkbusTxBuffer* nextFullTxBuffer(void) +{ + BOOL found = TRUE; + static uint8_t bufferIndex = 0; + uint8_t count = 0; + + while(tx_buffer[bufferIndex][0] == '\0') + { + if(++count >= LINKBUS_NUMBER_OF_TX_MSG_BUFFERS) + { + found = FALSE; + break; + } + + bufferIndex++; + if(bufferIndex >= LINKBUS_NUMBER_OF_TX_MSG_BUFFERS) + { + bufferIndex = 0; + } + } + + if(found) + { + return( &tx_buffer[bufferIndex]); + } + + return(null); +} + +LinkbusTxBuffer* nextEmptyTxBuffer(void) +{ + BOOL found = TRUE; + static uint8_t bufferIndex = 0; + uint8_t count = 0; + + while(tx_buffer[bufferIndex][0] != '\0') + { + if(++count >= LINKBUS_NUMBER_OF_TX_MSG_BUFFERS) + { + found = FALSE; + break; + } + + bufferIndex++; + if(bufferIndex >= LINKBUS_NUMBER_OF_TX_MSG_BUFFERS) + { + bufferIndex = 0; + } + } + + if(found) + { + return( &tx_buffer[bufferIndex]); + } + + return(null); +} + +LinkbusRxBuffer* nextEmptyRxBuffer(void) +{ + BOOL found = TRUE; + static uint8_t bufferIndex = 0; + uint8_t count = 0; + + while(rx_buffer[bufferIndex].id != MESSAGE_EMPTY) + { + if(++count >= LINKBUS_NUMBER_OF_RX_MSG_BUFFERS) + { + found = FALSE; + break; + } + + bufferIndex++; + if(bufferIndex >= LINKBUS_NUMBER_OF_RX_MSG_BUFFERS) + { + bufferIndex = 0; + } + } + + if(found) + { + return( &rx_buffer[bufferIndex]); + } + + return(null); +} + +LinkbusRxBuffer* nextFullRxBuffer(void) +{ + BOOL found = TRUE; + static uint8_t bufferIndex = 0; + uint8_t count = 0; + + while(rx_buffer[bufferIndex].id == MESSAGE_EMPTY) + { + if(++count >= LINKBUS_NUMBER_OF_RX_MSG_BUFFERS) + { + found = FALSE; + break; + } + + bufferIndex++; + if(bufferIndex >= LINKBUS_NUMBER_OF_RX_MSG_BUFFERS) + { + bufferIndex = 0; + } + } + + if(found) + { + return( &rx_buffer[bufferIndex]); + } + + return(null); +} + + +/*********************************************************************** + * linkbusTxInProgress(void) + ************************************************************************/ +BOOL linkbusTxInProgress(void) +{ + return(linkbus_tx_active); +} + +BOOL linkbus_start_tx(void) +{ + BOOL success = !linkbus_tx_active; + + if(success) /* message will be lost if transmit is busy */ + { + linkbus_tx_active = TRUE; + UCSR0B |= (1 << UDRIE0); + } + + return(success); +} + +void linkbus_end_tx(void) +{ + if(linkbus_tx_active) + { + UCSR0B &= ~(1 << UDRIE0); + linkbus_tx_active = FALSE; + } +} + +void linkbus_reset_rx(void) +{ + if(UCSR0B & (1 << RXEN0)) /* perform only if rx is currently enabled */ + { + UCSR0B &= ~(1 << RXEN0); +/* uint16_t s = sizeof(rx_buffer); // test */ + memset(rx_buffer, 0, sizeof(rx_buffer)); +/* if(s) s = 0; // test */ + UCSR0B |= (1 << RXEN0); + } +} + +void linkbus_init(uint32_t baud) +{ + memset(rx_buffer, 0, sizeof(rx_buffer)); + + for(int bufferIndex = 0; bufferIndex < LINKBUS_NUMBER_OF_TX_MSG_BUFFERS; bufferIndex++) + { + tx_buffer[bufferIndex][0] = '\0'; + } + + /*Set baud rate */ + uint16_t myubrr = MYUBRR(baud); + UBRR0H = (uint8_t)(myubrr >> 8); + UBRR0L = (uint8_t)myubrr; + /* Enable receiver and transmitter and related interrupts */ + UCSR0B = (1 << RXEN0) | (1 << TXEN0) | (1 << RXCIE0); +/* UCSR0B = (1< LINKBUS_MAX_MSG_LENGTH) + { + return( TRUE); + } + strncpy(g_tempMsgBuff, str, LINKBUS_MAX_MSG_LENGTH); + linkbus_send_text(g_tempMsgBuff); + return( FALSE); +} + +void lb_send_value(uint16_t value, char* label) +{ + sprintf(g_tempMsgBuff, "> %s=%d%s", label, value, lineTerm); + linkbus_send_text(g_tempMsgBuff); +} + +/*********************************************************************** + * lb_send_Help(void) + ************************************************************************/ +void lb_send_Help(void) +{ + if(g_bus_disabled) + { + return; + } + + sprintf(g_tempMsgBuff, "\n*** %s Ver. %s ***", PRODUCT_NAME_LONG, SW_REVISION); + + while(linkbus_send_text(g_tempMsgBuff)) + { + ; + } + while(linkbusTxInProgress()) + { + ; + } + + size_t n = sizeof(textHelp) / sizeof(textHelp[0]); + for(uint8_t i = 0; i < n; i++) + { + while(linkbus_send_text((char*)textHelp[i])) + { + ; + } + while(linkbusTxInProgress()) + { + ; + } + } + + lb_send_NewLine(); +} + diff --git a/linkbus.h b/Arduino-microfox/linkbus.h similarity index 96% rename from linkbus.h rename to Arduino-microfox/linkbus.h index b8c6e76..2465d8f 100644 --- a/linkbus.h +++ b/Arduino-microfox/linkbus.h @@ -1,252 +1,252 @@ -/********************************************************************************************** - * Copyright � 2017 Digital Confections LLC - * - * Permission is hereby granted, free of charge, to any person obtaining a copy of - * this software and associated documentation files (the "Software"), to deal in the - * Software without restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, subject to the - * following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, - * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE - * FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - ********************************************************************************************** - * - * linkbus.h - a simple serial inter-processor communication protocol. - */ - -#ifndef LINKBUS_H_ -#define LINKBUS_H_ - -#include "defs.h" -//#include "transmitter.h" -//#include "si5351.h" - -#define LINKBUS_MAX_MSG_LENGTH 50 -#define LINKBUS_MIN_MSG_LENGTH 3 /* shortest message: $TTY; */ -#define LINKBUS_MAX_MSG_FIELD_LENGTH 21 -#define LINKBUS_MAX_MSG_NUMBER_OF_FIELDS 3 -#define LINKBUS_NUMBER_OF_RX_MSG_BUFFERS 2 -#define LINKBUS_MAX_TX_MSG_LENGTH 40 -#define LINKBUS_NUMBER_OF_TX_MSG_BUFFERS 10 - -#define LINKBUS_POWERUP_DELAY_SECONDS 6 - -#define LINKBUS_MIN_TX_INTERVAL_MS 100 - -#define FOSC 16000000 /* Clock Speed */ -#define BAUD 57600 -#define MYUBRR(b) (FOSC / 16 / (b) - 1) - -typedef enum -{ - EMPTY_BUFF, - FULL_BUFF -} BufferState; - -/* Linkbus Messages - * Message formats: - * $id,f1,f2... fn; - * !id,f1,f2,... fn; - * $id,f1,f2,... fn? - * - * where - * $ = command - ! indicates a response or broadcast to subscribers - * id = linkbus MessageID - * fn = variable length fields - * ; = end of message flag - ? = end of query - * Null fields in settings commands indicates no change should be applied - * All null fields indicates a polling request for current settings - * ? terminator indicates subscription request to value changes - * Sending a query with fields containing data, is the equivalent of sending - * a command followed by a query (i.e., a response is requested). - * - * TEST EQUIPMENT MESSAGE FAMILY (DEVICE MESSAGING) - * $TST - Test message - * !ACK - Simple acknowledgment to a command (sent when required) - * $CK0 - Set Si5351 CLK0: field1 = freq (Hz); field2 = enable (BOOL) - * $CK1 - Set Si5351 CLK1: field1 = freq (Hz); field2 = enable (BOOL) - * $CK2 - Set Si5351 CLK2: field1 = freq (Hz); field2 = enable (BOOL) - * $VOL - Set audio volume: field1 = inc/decr (BOOL); field2 = % (int) - * $BAT? - Subscribe to battery voltage reports - * - * DUAL-BAND RX MESSAGE FAMILY (FUNCTIONAL MESSAGING) - * $BND - Set/Get radio band to 2m or 80m - * $S? - Subscribe to signal strength reports - * - Subscribe to gain setting reports - * - - */ - -typedef enum -{ - MESSAGE_EMPTY = 0, - - /* TEST EQUIPMENT MESSAGE FAMILY (TEST DEVICE MESSAGING) */ - MESSAGE_BAND = 'B' * 100 + 'N' * 10 + 'D', /* $BND,; / $BND? / !BND,; // Set band; field1 = RadioBand */ - MESSAGE_TTY = 'T' * 100 + 'T' * 10 + 'Y', /* Adjust for PC communications interface (add crlf, etc.) */ - - /* DUAL-BAND TX MESSAGE FAMILY (FUNCTIONAL MESSAGING) */ - MESSAGE_CLOCK_CAL = 'C' * 100 + 'A' * 10 + 'L', /* Set Jerry's clock calibration value */ - 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 */ - - /* UTILITY MESSAGES */ - MESSAGE_RESET = 'R' * 100 + 'S' * 10 + 'T', /* Processor reset */ - MESSAGE_VERSION = 'V' * 100 + 'E' * 10 + + 'R', /* S/W version number */ - - INVALID_MESSAGE = UINT16_MAX /* This value must never overlap a valid message ID */ -} LBMessageID; - -typedef enum -{ - LINKBUS_MSG_UNKNOWN = 0, - LINKBUS_MSG_COMMAND, - LINKBUS_MSG_QUERY, - LINKBUS_MSG_REPLY, - LINKBUS_MSG_INVALID -} LBMessageType; - -typedef enum -{ - FIELD1 = 0, - FIELD2 = 1, - FIELD3 = 2 -} LBMessageField; - -typedef enum -{ - BATTERY_BROADCAST = 0x0001, - RSSI_BROADCAST = 0x0002, - RF_BROADCAST = 0x0004, - UPC_TEMP_BROADCAST = 0x0008, - ALL_BROADCASTS = 0x000FF -} LBbroadcastType; - -typedef enum -{ - NO_ID = 0, - CONTROL_HEAD_ID = 1, - RECEIVER_ID = 2, - TRANSMITTER_ID = 3 -} DeviceID; - -typedef char LinkbusTxBuffer[LINKBUS_MAX_TX_MSG_LENGTH]; - -typedef struct -{ - LBMessageType type; - LBMessageID id; - char fields[LINKBUS_MAX_MSG_NUMBER_OF_FIELDS][LINKBUS_MAX_MSG_FIELD_LENGTH]; -} LinkbusRxBuffer; - -#define WAITING_FOR_UPDATE -1 - -/** - */ -void linkbus_init(uint32_t baud); - -/** - * Immediately turns off receiver and flushes receive buffer - */ -void linkbus_disable(void); - -/** - * Undoes linkbus_disable() - */ -void linkbus_enable(void); - - -/** - */ -void linkbus_end_tx(void); - -/** - */ -void linkbus_reset_rx(void); - -/** - */ -LinkbusTxBuffer* nextEmptyTxBuffer(void); - -/** - */ -LinkbusTxBuffer* nextFullTxBuffer(void); - -/** - */ -BOOL linkbusTxInProgress(void); - -/** - */ -LinkbusRxBuffer* nextEmptyRxBuffer(void); - -/** - */ -LinkbusRxBuffer* nextFullRxBuffer(void); - -/** - */ -void lb_send_sync(void); - -/** - */ -BOOL linkbus_send_text(char* text); - -/** -*/ -void lb_send_ESP(LBMessageType msgType, char* msg); - -/** - */ -void lb_send_msg(LBMessageType msgType, char* msgLabel, char* msgStr); - -/** - */ -void lb_broadcast_num(uint16_t data, char* str); - -/** - */ -void lb_send_Help(void); - -/** - */ -void lb_send_NewPrompt(void); - -/** - */ -void lb_send_NewLine(void); - -/** - */ -void linkbus_setLineTerm(char* term); - -/** - */ -void lb_echo_char(uint8_t c); - -/** - */ -BOOL lb_send_string(char* str); - -/** - */ -void lb_send_value(uint16_t value, char* label); - -/** - */ -void lb_send_Help(void); - -#endif /* LINKBUS_H_ */ +/********************************************************************************************** + * Copyright � 2017 Digital Confections LLC + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in the + * Software without restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the + * following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR + * PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE + * FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + ********************************************************************************************** + * + * linkbus.h - a simple serial inter-processor communication protocol. + */ + +#ifndef LINKBUS_H_ +#define LINKBUS_H_ + +#include "defs.h" +//#include "transmitter.h" +//#include "si5351.h" + +#define LINKBUS_MAX_MSG_LENGTH 50 +#define LINKBUS_MIN_MSG_LENGTH 3 /* shortest message: $TTY; */ +#define LINKBUS_MAX_MSG_FIELD_LENGTH 21 +#define LINKBUS_MAX_MSG_NUMBER_OF_FIELDS 3 +#define LINKBUS_NUMBER_OF_RX_MSG_BUFFERS 2 +#define LINKBUS_MAX_TX_MSG_LENGTH 40 +#define LINKBUS_NUMBER_OF_TX_MSG_BUFFERS 10 + +#define LINKBUS_POWERUP_DELAY_SECONDS 6 + +#define LINKBUS_MIN_TX_INTERVAL_MS 100 + +#define FOSC 16000000 /* Clock Speed */ +#define BAUD 57600 +#define MYUBRR(b) (FOSC / 16 / (b) - 1) + +typedef enum +{ + EMPTY_BUFF, + FULL_BUFF +} BufferState; + +/* Linkbus Messages + * Message formats: + * $id,f1,f2... fn; + * !id,f1,f2,... fn; + * $id,f1,f2,... fn? + * + * where + * $ = command - ! indicates a response or broadcast to subscribers + * id = linkbus MessageID + * fn = variable length fields + * ; = end of message flag - ? = end of query + * Null fields in settings commands indicates no change should be applied + * All null fields indicates a polling request for current settings + * ? terminator indicates subscription request to value changes + * Sending a query with fields containing data, is the equivalent of sending + * a command followed by a query (i.e., a response is requested). + * + * TEST EQUIPMENT MESSAGE FAMILY (DEVICE MESSAGING) + * $TST - Test message + * !ACK - Simple acknowledgment to a command (sent when required) + * $CK0 - Set Si5351 CLK0: field1 = freq (Hz); field2 = enable (BOOL) + * $CK1 - Set Si5351 CLK1: field1 = freq (Hz); field2 = enable (BOOL) + * $CK2 - Set Si5351 CLK2: field1 = freq (Hz); field2 = enable (BOOL) + * $VOL - Set audio volume: field1 = inc/decr (BOOL); field2 = % (int) + * $BAT? - Subscribe to battery voltage reports + * + * DUAL-BAND RX MESSAGE FAMILY (FUNCTIONAL MESSAGING) + * $BND - Set/Get radio band to 2m or 80m + * $S? - Subscribe to signal strength reports + * - Subscribe to gain setting reports + * - + */ + +typedef enum +{ + MESSAGE_EMPTY = 0, + + /* TEST EQUIPMENT MESSAGE FAMILY (TEST DEVICE MESSAGING) */ + MESSAGE_BAND = 'B' * 100 + 'N' * 10 + 'D', /* $BND,; / $BND? / !BND,; // Set band; field1 = RadioBand */ + MESSAGE_TTY = 'T' * 100 + 'T' * 10 + 'Y', /* Adjust for PC communications interface (add crlf, etc.) */ + + /* DUAL-BAND TX MESSAGE FAMILY (FUNCTIONAL MESSAGING) */ + MESSAGE_CLOCK_CAL = 'C' * 100 + 'A' * 10 + 'L', /* Set Jerry's clock calibration value */ + 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 */ + + /* UTILITY MESSAGES */ + MESSAGE_RESET = 'R' * 100 + 'S' * 10 + 'T', /* Processor reset */ + MESSAGE_VERSION = 'V' * 100 + 'E' * 10 + + 'R', /* S/W version number */ + + INVALID_MESSAGE = UINT16_MAX /* This value must never overlap a valid message ID */ +} LBMessageID; + +typedef enum +{ + LINKBUS_MSG_UNKNOWN = 0, + LINKBUS_MSG_COMMAND, + LINKBUS_MSG_QUERY, + LINKBUS_MSG_REPLY, + LINKBUS_MSG_INVALID +} LBMessageType; + +typedef enum +{ + FIELD1 = 0, + FIELD2 = 1, + FIELD3 = 2 +} LBMessageField; + +typedef enum +{ + BATTERY_BROADCAST = 0x0001, + RSSI_BROADCAST = 0x0002, + RF_BROADCAST = 0x0004, + UPC_TEMP_BROADCAST = 0x0008, + ALL_BROADCASTS = 0x000FF +} LBbroadcastType; + +typedef enum +{ + NO_ID = 0, + CONTROL_HEAD_ID = 1, + RECEIVER_ID = 2, + TRANSMITTER_ID = 3 +} DeviceID; + +typedef char LinkbusTxBuffer[LINKBUS_MAX_TX_MSG_LENGTH]; + +typedef struct +{ + LBMessageType type; + LBMessageID id; + char fields[LINKBUS_MAX_MSG_NUMBER_OF_FIELDS][LINKBUS_MAX_MSG_FIELD_LENGTH]; +} LinkbusRxBuffer; + +#define WAITING_FOR_UPDATE -1 + +/** + */ +void linkbus_init(uint32_t baud); + +/** + * Immediately turns off receiver and flushes receive buffer + */ +void linkbus_disable(void); + +/** + * Undoes linkbus_disable() + */ +void linkbus_enable(void); + + +/** + */ +void linkbus_end_tx(void); + +/** + */ +void linkbus_reset_rx(void); + +/** + */ +LinkbusTxBuffer* nextEmptyTxBuffer(void); + +/** + */ +LinkbusTxBuffer* nextFullTxBuffer(void); + +/** + */ +BOOL linkbusTxInProgress(void); + +/** + */ +LinkbusRxBuffer* nextEmptyRxBuffer(void); + +/** + */ +LinkbusRxBuffer* nextFullRxBuffer(void); + +/** + */ +void lb_send_sync(void); + +/** + */ +BOOL linkbus_send_text(char* text); + +/** +*/ +void lb_send_ESP(LBMessageType msgType, char* msg); + +/** + */ +void lb_send_msg(LBMessageType msgType, char* msgLabel, char* msgStr); + +/** + */ +void lb_broadcast_num(uint16_t data, char* str); + +/** + */ +void lb_send_Help(void); + +/** + */ +void lb_send_NewPrompt(void); + +/** + */ +void lb_send_NewLine(void); + +/** + */ +void linkbus_setLineTerm(char* term); + +/** + */ +void lb_echo_char(uint8_t c); + +/** + */ +BOOL lb_send_string(char* str); + +/** + */ +void lb_send_value(uint16_t value, char* label); + +/** + */ +void lb_send_Help(void); + +#endif /* LINKBUS_H_ */ From 895bb5c98f7385b3265758e0f1995f42d728a4a5 Mon Sep 17 00:00:00 2001 From: DigitalConfections Date: Tue, 26 May 2020 08:54:48 -0400 Subject: [PATCH 6/6] Moved Files Moved License and Readme outside of script folder. --- Arduino-microfox/LICENSE => LICENSE | 0 Arduino-microfox/README.md => README.md | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename Arduino-microfox/LICENSE => LICENSE (100%) rename Arduino-microfox/README.md => README.md (100%) diff --git a/Arduino-microfox/LICENSE b/LICENSE similarity index 100% rename from Arduino-microfox/LICENSE rename to LICENSE diff --git a/Arduino-microfox/README.md b/README.md similarity index 100% rename from Arduino-microfox/README.md rename to README.md