commit
c11c6bc8a0
|
@ -1,14 +1,12 @@
|
|||
|
||||
/* */
|
||||
/* 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 */
|
||||
/* */
|
||||
/* */
|
||||
/*
|
||||
* 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 <EEPROM.h> */
|
||||
|
||||
#define MAX_PATTERN_TEXT_LENGTH 20
|
||||
|
||||
|
@ -37,6 +35,7 @@ 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;
|
||||
|
@ -46,6 +45,7 @@ static volatile int16_t g_ID_period_seconds = EEPROM_ID_TIME_INTERVAL_DEFAULT;
|
|||
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' };
|
||||
|
||||
|
@ -60,13 +60,19 @@ 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 */
|
||||
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(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 */
|
||||
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);
|
||||
|
@ -76,13 +82,17 @@ 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 */
|
||||
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
|
||||
|
@ -95,10 +105,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
|
||||
* */
|
||||
|
@ -201,8 +207,11 @@ void setup()
|
|||
* 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");
|
||||
linkbus_send_text((char*)"Type \"GO\"\n");
|
||||
lb_send_NewPrompt();
|
||||
|
||||
while(( digitalRead(3) == LOW) && !g_start_override)
|
||||
{
|
||||
|
@ -211,8 +220,17 @@ void setup()
|
|||
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;
|
||||
|
||||
|
@ -238,11 +256,12 @@ 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;
|
||||
static uint8_t field_len = 0;
|
||||
static uint32_t msg_ID = 0;
|
||||
static int msg_ID = 0;
|
||||
static BOOL receiving_msg = FALSE;
|
||||
uint8_t rx_char;
|
||||
|
||||
|
@ -256,27 +275,95 @@ ISR(USART_RX_vect)
|
|||
if(buff)
|
||||
{
|
||||
rx_char = toupper(rx_char);
|
||||
SMCR = 0x00; /* exit power-down mode */
|
||||
/* 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;
|
||||
/* if(g_terminal_mode)
|
||||
* { */
|
||||
static uint8_t ignoreCount = 0;
|
||||
|
||||
/* Empty the field buffers */
|
||||
for(field_index = 0; field_index < LINKBUS_MAX_MSG_NUMBER_OF_FIELDS; field_index++)
|
||||
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 */
|
||||
}
|
||||
|
||||
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(receiving_msg)
|
||||
else if(rx_char)
|
||||
{
|
||||
if((rx_char == ',') || (rx_char == ';') || (rx_char == '?')) /* new field = ,; end of message = ; */
|
||||
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)
|
||||
|
@ -286,28 +373,6 @@ ISR(USART_RX_vect)
|
|||
|
||||
field_index++;
|
||||
field_len = 0;
|
||||
|
||||
if(rx_char == ';')
|
||||
{
|
||||
if(charIndex >= LINKBUS_MIN_MSG_LENGTH)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
if(!receiving_msg)
|
||||
{
|
||||
buff = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -321,21 +386,39 @@ ISR(USART_RX_vect)
|
|||
buff->fields[field_index - 1][field_len++] = rx_char;
|
||||
}
|
||||
}
|
||||
|
||||
charIndex = MIN(charIndex + 1, LINKBUS_MAX_MSG_FIELD_LENGTH);
|
||||
}
|
||||
else if(rx_char == 0x0D) /* Handle carriage return */
|
||||
}
|
||||
else
|
||||
{
|
||||
buff->id = (LBMessageID)LINKBUS_MSG_UNKNOWN;
|
||||
charIndex = LINKBUS_MAX_MSG_LENGTH;
|
||||
field_len = 0;
|
||||
msg_ID = LINKBUS_MSG_UNKNOWN;
|
||||
if((rx_char == 0x7F) || (rx_char == ' ')) /* Handle backspace and Space */
|
||||
{
|
||||
rx_char = '\0';
|
||||
}
|
||||
else /* start of new message */
|
||||
{
|
||||
uint8_t i;
|
||||
field_index = 0;
|
||||
buff = NULL;
|
||||
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';
|
||||
}
|
||||
|
||||
if(++charIndex >= LINKBUS_MAX_MSG_LENGTH)
|
||||
receiving_msg = TRUE;
|
||||
charIndex = MIN(charIndex + 1, LINKBUS_MAX_MSG_FIELD_LENGTH);
|
||||
}
|
||||
}
|
||||
|
||||
if(rx_char)
|
||||
{
|
||||
receiving_msg = FALSE;
|
||||
charIndex = 0;
|
||||
lb_echo_char(rx_char);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -460,6 +543,14 @@ void Send_Message(int imessage, int speed)
|
|||
{
|
||||
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)
|
||||
{
|
||||
|
@ -511,7 +602,6 @@ void Send_Message(int imessage, int speed)
|
|||
**
|
||||
****************************************** */
|
||||
void word_space(int speed)
|
||||
|
||||
{
|
||||
int time;
|
||||
|
||||
|
@ -589,7 +679,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
|
||||
|
@ -723,7 +813,7 @@ void loop()
|
|||
message = 0x0F; /* O */
|
||||
Send_Message(message, speed);
|
||||
word_space(speed);
|
||||
message = 0x20; /* 5 */
|
||||
message = TX5; /* 5 make A0 so to get around space issue */
|
||||
Send_Message(message, speed);
|
||||
word_space(speed);
|
||||
handleLinkBusMsgs();
|
||||
|
@ -818,8 +908,8 @@ int codeBits(char alphaNum)
|
|||
case '4': /* 4 ....- 00110000 0x30 */
|
||||
{ return( 0x30); }
|
||||
|
||||
case '5': /* 5 ..... 00100000 0x20 */
|
||||
{ return( 0x20); }
|
||||
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); }
|
||||
|
@ -931,12 +1021,6 @@ void __attribute__((optimize("O0"))) handleLinkBusMsgs()
|
|||
|
||||
switch(msg_id)
|
||||
{
|
||||
case MESSAGE_WIFI:
|
||||
{
|
||||
/* Your code goes here */
|
||||
}
|
||||
break;
|
||||
|
||||
case MESSAGE_RESET:
|
||||
{
|
||||
#ifdef USE_WATCHDOG
|
||||
|
@ -945,8 +1029,9 @@ void __attribute__((optimize("O0"))) handleLinkBusMsgs()
|
|||
{
|
||||
;
|
||||
}
|
||||
#endif /* USE_WATCHDOG */
|
||||
#else
|
||||
resetFunc(); /*call reset */
|
||||
#endif /* USE_WATCHDOG */
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -966,7 +1051,6 @@ void __attribute__((optimize("O0"))) handleLinkBusMsgs()
|
|||
|
||||
sprintf(g_tempStr, "DIP=%u\n", g_override_DIP_switches);
|
||||
linkbus_send_text(g_tempStr);
|
||||
send_ack = FALSE;
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -988,20 +1072,28 @@ void __attribute__((optimize("O0"))) handleLinkBusMsgs()
|
|||
|
||||
sprintf(g_tempStr, "LED:%s\n", g_enable_LEDs ? "ON" : "OFF");
|
||||
linkbus_send_text(g_tempStr);
|
||||
send_ack = FALSE;
|
||||
}
|
||||
break;
|
||||
|
||||
case MESSAGE_TX_POWER:
|
||||
case MESSAGE_SYNC_ENABLE:
|
||||
{
|
||||
/* Your code goes here */
|
||||
if(lb_buff->fields[FIELD1][0])
|
||||
{
|
||||
if((lb_buff->fields[FIELD1][1] == 'F') || (lb_buff->fields[FIELD1][0] == '0'))
|
||||
{
|
||||
g_enable_sync = FALSE;
|
||||
}
|
||||
break;
|
||||
|
||||
case MESSAGE_PERM:
|
||||
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:
|
||||
|
@ -1015,7 +1107,6 @@ void __attribute__((optimize("O0"))) handleLinkBusMsgs()
|
|||
g_start_override = TRUE;
|
||||
linkbus_send_text((char*)"We're off!\n");
|
||||
}
|
||||
send_ack = FALSE;
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -1023,7 +1114,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;
|
||||
|
||||
|
@ -1044,7 +1143,6 @@ void __attribute__((optimize("O0"))) handleLinkBusMsgs()
|
|||
|
||||
sprintf(g_tempStr, "Cal=%u\n", g_clock_calibration);
|
||||
linkbus_send_text(g_tempStr);
|
||||
send_ack = FALSE;
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -1064,53 +1162,27 @@ void __attribute__((optimize("O0"))) handleLinkBusMsgs()
|
|||
|
||||
sprintf(g_tempStr, "ID:%s\n", g_messages_text[STATION_ID]);
|
||||
linkbus_send_text(g_tempStr);
|
||||
send_ack = FALSE;
|
||||
}
|
||||
break;
|
||||
|
||||
case MESSAGE_CODE_SPEED:
|
||||
case MESSAGE_VERSION:
|
||||
{
|
||||
/* Your code goes here */
|
||||
}
|
||||
break;
|
||||
|
||||
case MESSAGE_TIME_INTERVAL:
|
||||
{
|
||||
/* 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_BAND:
|
||||
{
|
||||
/* Your code goes here */
|
||||
}
|
||||
break;
|
||||
|
||||
case MESSAGE_BAT:
|
||||
{
|
||||
/* Your code goes here */
|
||||
sprintf(g_tempStr, "SW Ver:%s\n", SW_REVISION);
|
||||
linkbus_send_text(g_tempStr);
|
||||
}
|
||||
break;
|
||||
|
||||
case MESSAGE_TEMP:
|
||||
{
|
||||
/* Your code goes here */
|
||||
float temp = getTemp();
|
||||
sprintf(g_tempStr, "Temp: %dC\n", (int)temp);
|
||||
linkbus_send_text(g_tempStr);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
{
|
||||
linkbus_reset_rx(); /* flush buffer */
|
||||
g_last_error_code = ERROR_CODE_ILLEGAL_COMMAND_RCVD;
|
||||
lb_send_Help();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -1118,7 +1190,7 @@ void __attribute__((optimize("O0"))) handleLinkBusMsgs()
|
|||
lb_buff->id = (LBMessageID)MESSAGE_EMPTY;
|
||||
if(send_ack)
|
||||
{
|
||||
linkbus_send_text((char*)MESSAGE_ACK);
|
||||
lb_send_NewPrompt();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1150,6 +1222,7 @@ void initializeEEPROMVars()
|
|||
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++)
|
||||
{
|
||||
|
@ -1177,6 +1250,7 @@ void initializeEEPROMVars()
|
|||
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();
|
||||
|
@ -1197,6 +1271,7 @@ void saveAllEEPROM()
|
|||
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++)
|
||||
{
|
||||
|
@ -1213,3 +1288,45 @@ void saveAllEEPROM()
|
|||
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);
|
||||
}
|
|
@ -36,20 +36,10 @@
|
|||
//#define TRANQUILIZE_WATCHDOG
|
||||
|
||||
#define PRODUCT_NAME_SHORT "ARDF Tx"
|
||||
#define PRODUCT_NAME_LONG "ARDF Dual-Band Transmitter"
|
||||
#define PRODUCT_NAME_LONG "WB8WFK ARDF Transmitter"
|
||||
|
||||
/*******************************************************/
|
||||
|
||||
/******************************************************
|
||||
* 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;
|
||||
|
@ -75,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 */
|
||||
/*******************************************************/
|
||||
|
@ -167,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"
|
||||
|
@ -185,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
|
||||
|
@ -296,47 +295,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,
|
||||
|
@ -346,38 +304,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,
|
||||
|
@ -386,15 +312,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 */
|
|
@ -0,0 +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 <string.h>
|
||||
//#include <stdio.h>
|
||||
//#include <avr/wdt.h>
|
||||
|
||||
/* 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<<RXEN0) | (1<<TXEN0);
|
||||
* Set frame format: 8data, 2stop bit */
|
||||
UCSR0C = (1 << USBS0) | (3 << UCSZ00);
|
||||
g_bus_disabled = FALSE;
|
||||
}
|
||||
|
||||
void linkbus_disable(void)
|
||||
{
|
||||
uint8_t bufferIndex;
|
||||
|
||||
g_bus_disabled = TRUE;
|
||||
UCSR0B = 0;
|
||||
linkbus_end_tx();
|
||||
memset(rx_buffer, 0, sizeof(rx_buffer));
|
||||
|
||||
for(bufferIndex = 0; bufferIndex < LINKBUS_NUMBER_OF_TX_MSG_BUFFERS; bufferIndex++)
|
||||
{
|
||||
tx_buffer[bufferIndex][0] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
void linkbus_enable(void)
|
||||
{
|
||||
uint8_t bufferIndex;
|
||||
|
||||
g_bus_disabled = FALSE;
|
||||
UCSR0B = (1 << RXEN0) | (1 << TXEN0) | (1 << RXCIE0);
|
||||
|
||||
memset(rx_buffer, 0, sizeof(rx_buffer));
|
||||
|
||||
for(bufferIndex = 0; bufferIndex < LINKBUS_NUMBER_OF_TX_MSG_BUFFERS; bufferIndex++)
|
||||
{
|
||||
tx_buffer[bufferIndex][0] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
BOOL linkbus_send_text(char* text)
|
||||
{
|
||||
BOOL err = TRUE;
|
||||
uint16_t tries = 200;
|
||||
|
||||
if(g_bus_disabled)
|
||||
{
|
||||
return( err);
|
||||
}
|
||||
|
||||
if(text)
|
||||
{
|
||||
LinkbusTxBuffer* buff = nextEmptyTxBuffer();
|
||||
|
||||
while(!buff && tries)
|
||||
{
|
||||
while(linkbusTxInProgress() && tries)
|
||||
{
|
||||
if(tries)
|
||||
{
|
||||
tries--; /* wait until transmit finishes */
|
||||
}
|
||||
}
|
||||
buff = nextEmptyTxBuffer();
|
||||
}
|
||||
|
||||
if(buff)
|
||||
{
|
||||
sprintf(*buff, text);
|
||||
|
||||
linkbus_start_tx();
|
||||
err = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return(err);
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************
|
||||
* Support for creating and sending various Linkbus messages is provided below.
|
||||
************************************************************************************/
|
||||
|
||||
void lb_send_msg(LBMessageType msgType, char* msgLabel, char* msgStr)
|
||||
{
|
||||
char prefix = '$';
|
||||
char terminus = ';';
|
||||
|
||||
if(msgType == LINKBUS_MSG_REPLY)
|
||||
{
|
||||
prefix = '!';
|
||||
}
|
||||
else if(msgType == LINKBUS_MSG_QUERY)
|
||||
{
|
||||
terminus = '?';
|
||||
}
|
||||
|
||||
sprintf(g_tempMsgBuff, "%c%s,%s%c", prefix, msgLabel, msgStr, terminus);
|
||||
|
||||
linkbus_send_text(g_tempMsgBuff);
|
||||
}
|
||||
|
||||
|
||||
void lb_send_sync(void)
|
||||
{
|
||||
sprintf(g_tempMsgBuff, ".....");
|
||||
linkbus_send_text(g_tempMsgBuff);
|
||||
}
|
||||
|
||||
|
||||
void lb_broadcast_num(uint16_t data, char* str)
|
||||
{
|
||||
char t[6] = "\0";
|
||||
|
||||
sprintf(t, "%u", data);
|
||||
g_tempMsgBuff[0] = '\0';
|
||||
|
||||
if(str)
|
||||
{
|
||||
sprintf(g_tempMsgBuff, "%s,%s;", str, t);
|
||||
}
|
||||
|
||||
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*)textPrompt);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* 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();
|
||||
}
|
||||
|
|
@ -35,16 +35,15 @@
|
|||
#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
|
||||
|
||||
#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
|
||||
|
@ -99,38 +98,18 @@ 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_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 */
|
||||
MESSAGE_GO = 'G' * 10 + 'O', /* Synchronizes clock */
|
||||
|
||||
/* 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;
|
||||
|
||||
#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,
|
||||
|
@ -164,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
|
||||
{
|
||||
|
@ -242,4 +221,32 @@ 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_ */
|
334
linkbus.cpp
334
linkbus.cpp
|
@ -1,334 +0,0 @@
|
|||
/**********************************************************************************************
|
||||
* 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 <string.h>
|
||||
//#include <stdio.h>
|
||||
//#include <avr/wdt.h>
|
||||
|
||||
/* Global Variables */
|
||||
static volatile BOOL g_bus_disabled = TRUE;
|
||||
|
||||
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<<RXEN0) | (1<<TXEN0); */
|
||||
/* Set frame format: 8data, 2stop bit */
|
||||
UCSR0C = (1 << USBS0) | (3 << UCSZ00);
|
||||
g_bus_disabled = FALSE;
|
||||
}
|
||||
|
||||
void linkbus_disable(void)
|
||||
{
|
||||
uint8_t bufferIndex;
|
||||
|
||||
g_bus_disabled = TRUE;
|
||||
UCSR0B = 0;
|
||||
linkbus_end_tx();
|
||||
memset(rx_buffer, 0, sizeof(rx_buffer));
|
||||
|
||||
for(bufferIndex=0; bufferIndex<LINKBUS_NUMBER_OF_TX_MSG_BUFFERS; bufferIndex++)
|
||||
{
|
||||
tx_buffer[bufferIndex][0] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
void linkbus_enable(void)
|
||||
{
|
||||
uint8_t bufferIndex;
|
||||
|
||||
g_bus_disabled = FALSE;
|
||||
UCSR0B = (1 << RXEN0) | (1 << TXEN0) | (1 << RXCIE0);
|
||||
|
||||
memset(rx_buffer, 0, sizeof(rx_buffer));
|
||||
|
||||
for(bufferIndex=0; bufferIndex<LINKBUS_NUMBER_OF_TX_MSG_BUFFERS; bufferIndex++)
|
||||
{
|
||||
tx_buffer[bufferIndex][0] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
BOOL linkbus_send_text(char* text)
|
||||
{
|
||||
BOOL err = TRUE;
|
||||
uint16_t tries = 200;
|
||||
|
||||
if(g_bus_disabled) return err;
|
||||
|
||||
if(text)
|
||||
{
|
||||
LinkbusTxBuffer* buff = nextEmptyTxBuffer();
|
||||
|
||||
while(!buff && tries)
|
||||
{
|
||||
while(linkbusTxInProgress() && tries)
|
||||
{
|
||||
if(tries) tries--; /* wait until transmit finishes */
|
||||
}
|
||||
buff = nextEmptyTxBuffer();
|
||||
}
|
||||
|
||||
if(buff)
|
||||
{
|
||||
sprintf(*buff, text);
|
||||
|
||||
linkbus_start_tx();
|
||||
err = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return(err);
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************
|
||||
* Support for creating and sending various Linkbus messages is provided below.
|
||||
************************************************************************************/
|
||||
|
||||
void lb_send_msg(LBMessageType msgType, char* msgLabel, char* msgStr)
|
||||
{
|
||||
char prefix = '$';
|
||||
char terminus = ';';
|
||||
|
||||
if(msgType == LINKBUS_MSG_REPLY)
|
||||
{
|
||||
prefix = '!';
|
||||
}
|
||||
else if(msgType == LINKBUS_MSG_QUERY)
|
||||
{
|
||||
terminus = '?';
|
||||
}
|
||||
|
||||
sprintf(g_tempMsgBuff, "%c%s,%s%c", prefix, msgLabel, msgStr, terminus);
|
||||
|
||||
linkbus_send_text(g_tempMsgBuff);
|
||||
}
|
||||
|
||||
|
||||
void lb_send_sync(void)
|
||||
{
|
||||
sprintf(g_tempMsgBuff, ".....");
|
||||
linkbus_send_text(g_tempMsgBuff);
|
||||
}
|
||||
|
||||
|
||||
void lb_broadcast_num(uint16_t data, char* str)
|
||||
{
|
||||
char t[6] = "\0";
|
||||
|
||||
sprintf(t, "%u", data);
|
||||
g_tempMsgBuff[0] = '\0';
|
||||
|
||||
if(str)
|
||||
{
|
||||
sprintf(g_tempMsgBuff, "%s,%s;", str, t);
|
||||
}
|
||||
|
||||
if(g_tempMsgBuff[0]) linkbus_send_text(g_tempMsgBuff);
|
||||
}
|
Ładowanie…
Reference in New Issue