commit
c11c6bc8a0
Plik diff jest za duży
Load Diff
|
@ -1,418 +1,335 @@
|
||||||
|
|
||||||
/**********************************************************************************************
|
/**********************************************************************************************
|
||||||
* Copyright <EFBFBD> 2017 Digital Confections LLC
|
* Copyright <EFBFBD> 2017 Digital Confections LLC
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
* 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
|
* this software and associated documentation files (the "Software"), to deal in the
|
||||||
* Software without restriction, including without limitation the rights to use, copy,
|
* Software without restriction, including without limitation the rights to use, copy,
|
||||||
* modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
|
* 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
|
* and to permit persons to whom the Software is furnished to do so, subject to the
|
||||||
* following conditions:
|
* following conditions:
|
||||||
*
|
*
|
||||||
* The above copyright notice and this permission notice shall be included in all
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
* copies or substantial portions of the Software.
|
* copies or substantial portions of the Software.
|
||||||
*
|
*
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
* 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
|
* 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
|
* 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
|
* 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
|
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
* DEALINGS IN THE SOFTWARE.
|
* DEALINGS IN THE SOFTWARE.
|
||||||
*
|
*
|
||||||
**********************************************************************************************/
|
**********************************************************************************************/
|
||||||
|
|
||||||
#ifndef DEFS_H
|
#ifndef DEFS_H
|
||||||
#define DEFS_H
|
#define DEFS_H
|
||||||
|
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
|
|
||||||
/* #define F_CPU 16000000UL / * gets declared in makefile * / */
|
/* #define F_CPU 16000000UL / * gets declared in makefile * / */
|
||||||
|
|
||||||
|
|
||||||
/******************************************************
|
/******************************************************
|
||||||
* Set the text that gets displayed to the user */
|
* Set the text that gets displayed to the user */
|
||||||
#define SW_REVISION "0.1"
|
#define SW_REVISION "0.1"
|
||||||
|
|
||||||
//#define TRANQUILIZE_WATCHDOG
|
//#define TRANQUILIZE_WATCHDOG
|
||||||
|
|
||||||
#define PRODUCT_NAME_SHORT "ARDF Tx"
|
#define PRODUCT_NAME_SHORT "ARDF Tx"
|
||||||
#define PRODUCT_NAME_LONG "ARDF Dual-Band Transmitter"
|
#define PRODUCT_NAME_LONG "WB8WFK ARDF Transmitter"
|
||||||
|
|
||||||
/*******************************************************/
|
/*******************************************************/
|
||||||
|
|
||||||
/******************************************************
|
#ifndef uint16_t_defined
|
||||||
* Include only the necessary hardware support */
|
#define uint16_t_defined
|
||||||
// #define INCLUDE_SI5351_SUPPORT // Silicon Labs Programmable Clock
|
typedef unsigned int uint16_t;
|
||||||
// #define INCLUDE_DS3231_SUPPORT // Maxim RTC
|
#endif
|
||||||
// #define INCLUDE_TRANSMITTER_SUPPORT
|
|
||||||
// #define INCLUDE_DAC081C085_SUPPORT
|
#ifndef uint32_t_defined
|
||||||
// #define ENABLE_PIN_CHANGE_INTERRUPT_0
|
#define uint32_t_defined
|
||||||
// #define ENABLE_PIN_CHANGE_INTERRUPT_1
|
typedef unsigned long uint32_t;
|
||||||
// #define ENABLE_PIN_CHANGE_INTERRUPT_2
|
#endif
|
||||||
|
|
||||||
#ifndef uint16_t_defined
|
#ifndef unit8_t_defined
|
||||||
#define uint16_t_defined
|
#define unit8_t_defined
|
||||||
typedef unsigned int uint16_t;
|
typedef unsigned char uint8_t;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef uint32_t_defined
|
#ifndef null
|
||||||
#define uint32_t_defined
|
#define null 0
|
||||||
typedef unsigned long uint32_t;
|
#endif
|
||||||
#endif
|
|
||||||
|
#ifdef INCLUDE_DAC081C085_SUPPORT
|
||||||
#ifndef unit8_t_defined
|
#define PA_DAC DAC081C_I2C_SLAVE_ADDR_A0
|
||||||
#define unit8_t_defined
|
#define AM_DAC DAC081C_I2C_SLAVE_ADDR_A1
|
||||||
typedef unsigned char uint8_t;
|
#define BIAS_DAC DAC081C_I2C_SLAVE_ADDR_A2
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef null
|
typedef enum {
|
||||||
#define null 0
|
// TX1 = 0xA4,
|
||||||
#endif
|
// TX2 = 0xA3,
|
||||||
|
// TX3 = 0xA2,
|
||||||
#ifdef INCLUDE_DAC081C085_SUPPORT
|
// TX4 = 0xA1,
|
||||||
#define PA_DAC DAC081C_I2C_SLAVE_ADDR_A0
|
TX5 = 0xA0
|
||||||
#define AM_DAC DAC081C_I2C_SLAVE_ADDR_A1
|
} Tx_t;
|
||||||
#define BIAS_DAC DAC081C_I2C_SLAVE_ADDR_A2
|
|
||||||
#endif
|
/*******************************************************/
|
||||||
|
/* Error Codes */
|
||||||
/*******************************************************/
|
/*******************************************************/
|
||||||
/* Error Codes */
|
typedef enum {
|
||||||
/*******************************************************/
|
ERROR_CODE_NO_ERROR = 0x00,
|
||||||
typedef enum {
|
ERROR_CODE_REPORT_NO_ERROR = 0x01,
|
||||||
ERROR_CODE_NO_ERROR = 0x00,
|
ERROR_CODE_2M_BIAS_SM_NOT_READY = 0xC6,
|
||||||
ERROR_CODE_REPORT_NO_ERROR = 0x01,
|
ERROR_CODE_EVENT_STATION_ID_ERROR = 0xC7,
|
||||||
ERROR_CODE_2M_BIAS_SM_NOT_READY = 0xC6,
|
ERROR_CODE_EVENT_PATTERN_CODE_SPEED_NOT_SPECIFIED = 0xC8,
|
||||||
ERROR_CODE_EVENT_STATION_ID_ERROR = 0xC7,
|
ERROR_CODE_EVENT_PATTERN_NOT_SPECIFIED = 0xC9,
|
||||||
ERROR_CODE_EVENT_PATTERN_CODE_SPEED_NOT_SPECIFIED = 0xC8,
|
ERROR_CODE_EVENT_TIMING_ERROR = 0xCA,
|
||||||
ERROR_CODE_EVENT_PATTERN_NOT_SPECIFIED = 0xC9,
|
ERROR_CODE_EVENT_MISSING_TRANSMIT_DURATION = 0xCB,
|
||||||
ERROR_CODE_EVENT_TIMING_ERROR = 0xCA,
|
ERROR_CODE_EVENT_MISSING_START_TIME = 0xCC,
|
||||||
ERROR_CODE_EVENT_MISSING_TRANSMIT_DURATION = 0xCB,
|
ERROR_CODE_EVENT_NOT_CONFIGURED = 0xCD,
|
||||||
ERROR_CODE_EVENT_MISSING_START_TIME = 0xCC,
|
ERROR_CODE_ILLEGAL_COMMAND_RCVD = 0xCE,
|
||||||
ERROR_CODE_EVENT_NOT_CONFIGURED = 0xCD,
|
ERROR_CODE_SW_LOGIC_ERROR = 0xCF,
|
||||||
ERROR_CODE_ILLEGAL_COMMAND_RCVD = 0xCE,
|
ERROR_CODE_POWER_LEVEL_NOT_SUPPORTED = 0xF5,
|
||||||
ERROR_CODE_SW_LOGIC_ERROR = 0xCF,
|
ERROR_CODE_NO_ANTENNA_PREVENTS_POWER_SETTING = 0xF6,
|
||||||
ERROR_CODE_POWER_LEVEL_NOT_SUPPORTED = 0xF5,
|
ERROR_CODE_NO_ANTENNA_FOR_BAND = 0xF7,
|
||||||
ERROR_CODE_NO_ANTENNA_PREVENTS_POWER_SETTING = 0xF6,
|
ERROR_CODE_WD_TIMEOUT = 0xF8,
|
||||||
ERROR_CODE_NO_ANTENNA_FOR_BAND = 0xF7,
|
ERROR_CODE_SUPPLY_VOLTAGE_ERROR = 0xF9,
|
||||||
ERROR_CODE_WD_TIMEOUT = 0xF8,
|
ERROR_CODE_BUCK_REG_OUTOFSPEC = 0xFA,
|
||||||
ERROR_CODE_SUPPLY_VOLTAGE_ERROR = 0xF9,
|
ERROR_CODE_CLKGEN_NONRESPONSIVE = 0xFB,
|
||||||
ERROR_CODE_BUCK_REG_OUTOFSPEC = 0xFA,
|
ERROR_CODE_RTC_NONRESPONSIVE = 0xFC,
|
||||||
ERROR_CODE_CLKGEN_NONRESPONSIVE = 0xFB,
|
ERROR_CODE_DAC3_NONRESPONSIVE = 0xFD,
|
||||||
ERROR_CODE_RTC_NONRESPONSIVE = 0xFC,
|
ERROR_CODE_DAC2_NONRESPONSIVE = 0xFE,
|
||||||
ERROR_CODE_DAC3_NONRESPONSIVE = 0xFD,
|
ERROR_CODE_DAC1_NONRESPONSIVE = 0xFF
|
||||||
ERROR_CODE_DAC2_NONRESPONSIVE = 0xFE,
|
} EC;
|
||||||
ERROR_CODE_DAC1_NONRESPONSIVE = 0xFF
|
|
||||||
} EC;
|
/*******************************************************/
|
||||||
|
/* Status Codes */
|
||||||
/*******************************************************/
|
/*******************************************************/
|
||||||
/* Status Codes */
|
typedef enum {
|
||||||
/*******************************************************/
|
STATUS_CODE_IDLE = 0x00,
|
||||||
typedef enum {
|
STATUS_CODE_REPORT_IDLE = 0x01,
|
||||||
STATUS_CODE_IDLE = 0x00,
|
STATUS_CODE_NO_ANT_ATTACHED = 0xE9,
|
||||||
STATUS_CODE_REPORT_IDLE = 0x01,
|
STATUS_CODE_2M_ANT_ATTACHED = 0xEA,
|
||||||
STATUS_CODE_NO_ANT_ATTACHED = 0xE9,
|
STATUS_CODE_80M_ANT_ATTACHED = 0xEB,
|
||||||
STATUS_CODE_2M_ANT_ATTACHED = 0xEA,
|
STATUS_CODE_RECEIVING_EVENT_DATA = 0xEC,
|
||||||
STATUS_CODE_80M_ANT_ATTACHED = 0xEB,
|
STATUS_CODE_RETURNED_FROM_SLEEP = 0xED,
|
||||||
STATUS_CODE_RECEIVING_EVENT_DATA = 0xEC,
|
STATUS_CODE_BEGINNING_XMSN_THIS_CYCLE = 0xEE,
|
||||||
STATUS_CODE_RETURNED_FROM_SLEEP = 0xED,
|
STATUS_CODE_SENDING_ID = 0xEF,
|
||||||
STATUS_CODE_BEGINNING_XMSN_THIS_CYCLE = 0xEE,
|
STATUS_CODE_EVENT_NEVER_ENDS = 0xFB,
|
||||||
STATUS_CODE_SENDING_ID = 0xEF,
|
STATUS_CODE_EVENT_FINISHED = 0xFC,
|
||||||
STATUS_CODE_EVENT_NEVER_ENDS = 0xFB,
|
STATUS_CODE_EVENT_STARTED_NOW_TRANSMITTING = 0xFD,
|
||||||
STATUS_CODE_EVENT_FINISHED = 0xFC,
|
STATUS_CODE_EVENT_STARTED_WAITING_FOR_TIME_SLOT = 0xFE,
|
||||||
STATUS_CODE_EVENT_STARTED_NOW_TRANSMITTING = 0xFD,
|
STATUS_CODE_WAITING_FOR_EVENT_START = 0xFF
|
||||||
STATUS_CODE_EVENT_STARTED_WAITING_FOR_TIME_SLOT = 0xFE,
|
} SC;
|
||||||
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 */
|
||||||
* ADC Scale Factors */
|
#define ADC_REF_VOLTAGE_mV 1100UL
|
||||||
/* 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 ADC_MAX_VOLTAGE_MV 4200L /* maximum voltage the ADC can read */
|
#define BATTERY_DROP 320L /* voltage drop between the battery terminals and the ADC input while powering the ESP8266 */
|
||||||
#define BATTERY_VOLTAGE_MAX_MV 4200L /* voltage at which the battery is considered to be fully charged */
|
#define BATTERY_DROP_OFFSET (BATTERY_DROP * 1023L)
|
||||||
#define BATTERY_DROP 320L /* voltage drop between the battery terminals and the ADC input while powering the ESP8266 */
|
#define VBAT(x) (BATTERY_DROP + (x * ADC_MAX_VOLTAGE_MV) / 1023L)
|
||||||
#define BATTERY_DROP_OFFSET (BATTERY_DROP * 1023L)
|
#define BATTERY_PERCENTAGE(x, y) ( ( 100L * ((x * ADC_MAX_VOLTAGE_MV + BATTERY_DROP_OFFSET) - (1023L * y)) ) / ((BATTERY_VOLTAGE_MAX_MV - y) * 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 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)
|
||||||
#define PA_VOLTAGE_MAX_MV 14100L
|
|
||||||
#define VPA(x)((x * PA_VOLTAGE_MAX_MV) / 1023L)
|
typedef uint16_t BatteryLevel; /* in milliVolts */
|
||||||
|
|
||||||
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_5 (((5000L - BATTERY_DROP) * 1023L) / BATTERY_VOLTAGE_MAX_MV)
|
#define VOLTS_3_0 (((3000L - BATTERY_DROP) * 1023L) / BATTERY_VOLTAGE_MAX_MV)
|
||||||
#define VOLTS_3_19 (((3190L - BATTERY_DROP) * 1023L) / BATTERY_VOLTAGE_MAX_MV)
|
#define VOLTS_2_4 (((2400L - 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 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 ANTENNA_DETECT_THRESH 20
|
|
||||||
#define ANTENNA_DETECT_DEBOUNCE 50
|
#define NUMBER_OF_ESSENTIAL_EVENT_PARAMETERS 14
|
||||||
|
|
||||||
#define NUMBER_OF_ESSENTIAL_EVENT_PARAMETERS 14
|
|
||||||
|
/*******************************************************/
|
||||||
|
|
||||||
/*******************************************************/
|
#ifndef SELECTIVELY_DISABLE_OPTIMIZATION
|
||||||
|
#define SELECTIVELY_DISABLE_OPTIMIZATION
|
||||||
#ifndef SELECTIVELY_DISABLE_OPTIMIZATION
|
#endif
|
||||||
#define SELECTIVELY_DISABLE_OPTIMIZATION
|
|
||||||
#endif
|
/******************************************************
|
||||||
|
* EEPROM definitions */
|
||||||
/******************************************************
|
#define EEPROM_INITIALIZED_FLAG 0xAD
|
||||||
* EEPROM definitions */
|
#define EEPROM_UNINITIALIZED 0x00
|
||||||
#define EEPROM_INITIALIZED_FLAG 0xAC
|
|
||||||
#define EEPROM_UNINITIALIZED 0x00
|
#define EEPROM_STATION_ID_DEFAULT "FOXBOX"
|
||||||
|
#define EEPROM_PATTERN_TEXT_DEFAULT "PARIS|"
|
||||||
#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_START_TIME_DEFAULT 0
|
#define EEPROM_EVENT_ENABLED_DEFAULT FALSE
|
||||||
#define EEPROM_FINISH_TIME_DEFAULT 0
|
#define EEPROM_ID_CODE_SPEED_DEFAULT 20
|
||||||
#define EEPROM_EVENT_ENABLED_DEFAULT FALSE
|
#define EEPROM_PATTERN_CODE_SPEED_DEFAULT 8
|
||||||
#define EEPROM_ID_CODE_SPEED_DEFAULT 20
|
#define EEPROM_ON_AIR_TIME_DEFAULT 60
|
||||||
#define EEPROM_PATTERN_CODE_SPEED_DEFAULT 8
|
#define EEPROM_OFF_AIR_TIME_DEFAULT 240
|
||||||
#define EEPROM_ON_AIR_TIME_DEFAULT 60
|
#define EEPROM_INTRA_CYCLE_DELAY_TIME_DEFAULT 0
|
||||||
#define EEPROM_OFF_AIR_TIME_DEFAULT 240
|
#define EEPROM_ID_TIME_INTERVAL_DEFAULT 300
|
||||||
#define EEPROM_INTRA_CYCLE_DELAY_TIME_DEFAULT 0
|
#define EEPROM_CLOCK_CALIBRATION_DEFAULT 15629
|
||||||
#define EEPROM_ID_TIME_INTERVAL_DEFAULT 300
|
#define EEPROM_OVERRIDE_DIP_SW_DEFAULT 0
|
||||||
#define EEPROM_CLOCK_CALIBRATION_DEFAULT 15629
|
#define EEPROM_ENABLE_LEDS_DEFAULT 1
|
||||||
#define EEPROM_OVERRIDE_DIP_SW_DEFAULT 0
|
#define EEPROM_ENABLE_SYNC_DEFAULT 1
|
||||||
#define EEPROM_ENABLE_LEDS_DEFAULT 1
|
|
||||||
|
#define EEPROM_SI5351_CALIBRATION_DEFAULT 0x00
|
||||||
#define EEPROM_SI5351_CALIBRATION_DEFAULT 0x00
|
#define EEPROM_CLK0_OUT_DEFAULT 133000000
|
||||||
#define EEPROM_CLK0_OUT_DEFAULT 133000000
|
#define EEPROM_CLK1_OUT_DEFAULT 70000000
|
||||||
#define EEPROM_CLK1_OUT_DEFAULT 70000000
|
#define EEPROM_CLK2_OUT_DEFAULT 10700000
|
||||||
#define EEPROM_CLK2_OUT_DEFAULT 10700000
|
#define EEPROM_CLK0_ONOFF_DEFAULT OFF
|
||||||
#define EEPROM_CLK0_ONOFF_DEFAULT OFF
|
#define EEPROM_CLK1_ONOFF_DEFAULT OFF
|
||||||
#define EEPROM_CLK1_ONOFF_DEFAULT OFF
|
#define EEPROM_CLK2_ONOFF_DEFAULT OFF
|
||||||
#define EEPROM_CLK2_ONOFF_DEFAULT OFF
|
|
||||||
|
#define EEPROM_BATTERY_EMPTY_MV 3430
|
||||||
#define EEPROM_BATTERY_EMPTY_MV 3430
|
|
||||||
|
/******************************************************
|
||||||
/******************************************************
|
* General definitions for making the code easier to understand */
|
||||||
* General definitions for making the code easier to understand */
|
#define SDA_PIN (1 << PINC4)
|
||||||
#define SDA_PIN (1 << PINC4)
|
#define SCL_PIN (1 << PINC5)
|
||||||
#define SCL_PIN (1 << PINC5)
|
#define I2C_PINS (SCL_PIN | SDA_PIN)
|
||||||
#define I2C_PINS (SCL_PIN | SDA_PIN)
|
|
||||||
|
#ifndef FALSE
|
||||||
#ifndef FALSE
|
#define FALSE 0
|
||||||
#define FALSE 0
|
#endif
|
||||||
#endif
|
|
||||||
|
#ifndef TRUE
|
||||||
#ifndef TRUE
|
#define TRUE !FALSE
|
||||||
#define TRUE !FALSE
|
#endif
|
||||||
#endif
|
|
||||||
|
#ifndef BOOL
|
||||||
#ifndef BOOL
|
typedef uint8_t BOOL;
|
||||||
typedef uint8_t BOOL;
|
#endif
|
||||||
#endif
|
|
||||||
|
#ifndef Frequency_Hz
|
||||||
#ifndef Frequency_Hz
|
typedef unsigned long Frequency_Hz;
|
||||||
typedef unsigned long Frequency_Hz;
|
#endif
|
||||||
#endif
|
|
||||||
|
#ifndef UINT16_MAX
|
||||||
#ifndef UINT16_MAX
|
#define UINT16_MAX __INT16_MAX__
|
||||||
#define UINT16_MAX __INT16_MAX__
|
#endif
|
||||||
#endif
|
|
||||||
|
#define ON 1
|
||||||
#define ON 1
|
#define OFF 0
|
||||||
#define OFF 0
|
#define TOGGLE 2
|
||||||
#define TOGGLE 2
|
|
||||||
|
#define UNDETERMINED 3
|
||||||
#define UNDETERMINED 3
|
|
||||||
|
#define MIN(A,B) ({ __typeof__(A) __a = (A); __typeof__(B) __b = (B); __a < __b ? __a : __b; })
|
||||||
#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 MAX(A,B) ({ __typeof__(A) __a = (A); __typeof__(B) __b = (B); __a < __b ? __b : __a; })
|
|
||||||
|
#define CLAMP(low, x, high) ({\
|
||||||
#define CLAMP(low, x, high) ({\
|
__typeof__(x) __x = (x); \
|
||||||
__typeof__(x) __x = (x); \
|
__typeof__(low) __low = (low);\
|
||||||
__typeof__(low) __low = (low);\
|
__typeof__(high) __high = (high);\
|
||||||
__typeof__(high) __high = (high);\
|
__x > __high ? __high : (__x < __low ? __low : __x);\
|
||||||
__x > __high ? __high : (__x < __low ? __low : __x);\
|
})
|
||||||
})
|
|
||||||
|
#define MAX_TIME 4294967295L
|
||||||
#define MAX_TIME 4294967295L
|
#define MAX_UINT16 65535
|
||||||
#define MAX_UINT16 65535
|
#define MAX_INT16 32767
|
||||||
#define MAX_INT16 32767
|
|
||||||
|
typedef enum
|
||||||
typedef enum
|
{
|
||||||
{
|
DOWN = -1,
|
||||||
DOWN = -1,
|
NOCHANGE = 0,
|
||||||
NOCHANGE = 0,
|
UP = 1,
|
||||||
UP = 1,
|
SETTOVALUE
|
||||||
SETTOVALUE
|
} IncrType;
|
||||||
} IncrType;
|
|
||||||
|
typedef enum
|
||||||
typedef enum
|
{
|
||||||
{
|
ANT_CONNECTION_UNDETERMINED,
|
||||||
ANT_CONNECTION_UNDETERMINED,
|
ANT_ALL_DISCONNECTED,
|
||||||
ANT_ALL_DISCONNECTED,
|
ANT_2M_CONNECTED,
|
||||||
ANT_2M_CONNECTED,
|
ANT_80M_CONNECTED,
|
||||||
ANT_80M_CONNECTED,
|
ANT_2M_AND_80M_CONNECTED
|
||||||
ANT_2M_AND_80M_CONNECTED
|
} AntConnType;
|
||||||
} AntConnType;
|
|
||||||
|
typedef enum
|
||||||
typedef enum
|
{
|
||||||
{
|
POWER_UP,
|
||||||
POWER_UP,
|
POWER_SLEEP
|
||||||
POWER_SLEEP
|
} InitActionType;
|
||||||
} InitActionType;
|
|
||||||
|
#define QUAD_MASK 0xC0
|
||||||
#define QUAD_MASK 0xC0
|
#define QUAD_A 7
|
||||||
#define QUAD_A 7
|
#define QUAD_B 6
|
||||||
#define QUAD_B 6
|
|
||||||
|
#define MAX_TONE_VOLUME_SETTING 15
|
||||||
#define MAX_TONE_VOLUME_SETTING 15
|
#define TONE_POT_VAL(x) (255 - (x*17))
|
||||||
#define TONE_POT_VAL(x) (255 - (x*17))
|
#define MAX_MAIN_VOLUME_SETTING 15
|
||||||
#define MAX_MAIN_VOLUME_SETTING 15
|
|
||||||
|
#define POWER_OFF_DELAY 5000
|
||||||
#define POWER_OFF_DELAY 5000
|
#define BACKLIGHT_OFF_DELAY 5000
|
||||||
#define BACKLIGHT_OFF_DELAY 5000
|
#define BACKLIGHT_ALWAYS_ON 65535
|
||||||
#define BACKLIGHT_ALWAYS_ON 65535
|
#define HEADPHONE_REMOVED_DELAY 100
|
||||||
#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 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 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 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 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
|
||||||
#define SEND_ID_DELAY 4100
|
|
||||||
|
/* Periodic TIMER2 interrupt timing definitions */
|
||||||
/* Periodic TIMER2 interrupt timing definitions */
|
#define TIMER2_57HZ 10
|
||||||
#define TIMER2_57HZ 10
|
#define TIMER2_20HZ 49
|
||||||
#define TIMER2_20HZ 49
|
#define TIMER2_5_8HZ 100
|
||||||
#define TIMER2_5_8HZ 100
|
#define TIMER2_0_5HZ 1000
|
||||||
#define TIMER2_0_5HZ 1000
|
|
||||||
|
#define BEEP_SHORT 100
|
||||||
#define BEEP_SHORT 100
|
#define BEEP_LONG 65535
|
||||||
#define BEEP_LONG 65535
|
|
||||||
|
/******************************************************
|
||||||
/******************************************************
|
* UI Hardware-related definitions */
|
||||||
* UI Hardware-related definitions */
|
|
||||||
|
typedef enum
|
||||||
typedef enum lcdRow
|
{
|
||||||
{
|
FrequencyFormat,
|
||||||
ROW0,
|
HourMinuteSecondFormat,
|
||||||
ROW1,
|
HourMinuteSecondDateFormat
|
||||||
NUMBER_OF_LCD_ROWS
|
} TextFormat;
|
||||||
} LcdRowType;
|
|
||||||
|
#define DISPLAY_WIDTH_STRING_SIZE (NUMBER_OF_LCD_COLS + 1)
|
||||||
typedef enum lcdColumn
|
|
||||||
{
|
typedef enum batteryType
|
||||||
COL0,
|
{
|
||||||
COL1,
|
BATTERY_9V,
|
||||||
COL2,
|
BATTERY_4r2V,
|
||||||
COL3,
|
BATTERY_EXTERNAL,
|
||||||
COL4,
|
BATTERY_UNKNOWN
|
||||||
COL5,
|
} BatteryType;
|
||||||
COL6,
|
|
||||||
COL7,
|
typedef enum
|
||||||
COL8,
|
{
|
||||||
COL9,
|
Minutes_Seconds, /* minutes up to 59 */
|
||||||
COL10,
|
Hours_Minutes_Seconds, /* hours up to 23 */
|
||||||
COL11,
|
Day_Month_Year_Hours_Minutes_Seconds, /* Year up to 99 */
|
||||||
COL12,
|
Minutes_Seconds_Elapsed, /* minutes up to 99 */
|
||||||
COL13,
|
Time_Format_Not_Specified
|
||||||
COL14,
|
} TimeFormat;
|
||||||
COL15,
|
|
||||||
COL16,
|
#define NO_TIME_SPECIFIED (-1)
|
||||||
COL17,
|
|
||||||
COL18,
|
#define SecondsFromHours(hours) ((hours) * 3600)
|
||||||
COL19,
|
#define SecondsFromMinutes(min) ((min) * 60)
|
||||||
NUMBER_OF_LCD_COLS,
|
|
||||||
INVALID_LCD_COLUMN
|
typedef enum
|
||||||
} LcdColType;
|
{
|
||||||
|
PATTERN_TEXT,
|
||||||
typedef enum
|
STATION_ID
|
||||||
{
|
} TextIndex;
|
||||||
BUTTON1_COLUMN = COL0,
|
|
||||||
BUTTON2_COLUMN = COL5,
|
#endif /* DEFS_H */
|
||||||
BUTTON3_COLUMN = COL10,
|
|
||||||
BUTTON4_COLUMN = COL15
|
|
||||||
} ButtonColumn;
|
|
||||||
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
FrequencyFormat,
|
|
||||||
HourMinuteSecondFormat,
|
|
||||||
HourMinuteSecondDateFormat
|
|
||||||
} TextFormat;
|
|
||||||
|
|
||||||
#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,
|
|
||||||
BATTERY_4r2V,
|
|
||||||
BATTERY_EXTERNAL,
|
|
||||||
BATTERY_UNKNOWN
|
|
||||||
} BatteryType;
|
|
||||||
|
|
||||||
typedef enum buttons
|
|
||||||
{
|
|
||||||
BUTTON1,
|
|
||||||
BUTTON2,
|
|
||||||
BUTTON3,
|
|
||||||
BUTTON4,
|
|
||||||
NUMBER_OF_BUTTONS
|
|
||||||
} ButtonType;
|
|
||||||
|
|
||||||
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 */
|
|
|
@ -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();
|
||||||
|
}
|
||||||
|
|
|
@ -1,245 +1,252 @@
|
||||||
/**********************************************************************************************
|
/**********************************************************************************************
|
||||||
* Copyright <EFBFBD> 2017 Digital Confections LLC
|
* Copyright <EFBFBD> 2017 Digital Confections LLC
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
* 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
|
* this software and associated documentation files (the "Software"), to deal in the
|
||||||
* Software without restriction, including without limitation the rights to use, copy,
|
* Software without restriction, including without limitation the rights to use, copy,
|
||||||
* modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
|
* 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
|
* and to permit persons to whom the Software is furnished to do so, subject to the
|
||||||
* following conditions:
|
* following conditions:
|
||||||
*
|
*
|
||||||
* The above copyright notice and this permission notice shall be included in all
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
* copies or substantial portions of the Software.
|
* copies or substantial portions of the Software.
|
||||||
*
|
*
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
* 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
|
* 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
|
* 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
|
* 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
|
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
* DEALINGS IN THE SOFTWARE.
|
* DEALINGS IN THE SOFTWARE.
|
||||||
*
|
*
|
||||||
**********************************************************************************************
|
**********************************************************************************************
|
||||||
*
|
*
|
||||||
* linkbus.h - a simple serial inter-processor communication protocol.
|
* linkbus.h - a simple serial inter-processor communication protocol.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef LINKBUS_H_
|
#ifndef LINKBUS_H_
|
||||||
#define LINKBUS_H_
|
#define LINKBUS_H_
|
||||||
|
|
||||||
#include "defs.h"
|
#include "defs.h"
|
||||||
//#include "transmitter.h"
|
//#include "transmitter.h"
|
||||||
//#include "si5351.h"
|
//#include "si5351.h"
|
||||||
|
|
||||||
#define LINKBUS_MAX_MSG_LENGTH 50
|
#define LINKBUS_MAX_MSG_LENGTH 50
|
||||||
#define LINKBUS_MIN_MSG_LENGTH 3 /* shortest message: $TTY; */
|
#define LINKBUS_MIN_MSG_LENGTH 3 /* shortest message: $TTY; */
|
||||||
#define LINKBUS_MAX_MSG_FIELD_LENGTH 21
|
#define LINKBUS_MAX_MSG_FIELD_LENGTH 21
|
||||||
#define LINKBUS_MAX_MSG_NUMBER_OF_FIELDS 3
|
#define LINKBUS_MAX_MSG_NUMBER_OF_FIELDS 3
|
||||||
#define LINKBUS_NUMBER_OF_RX_MSG_BUFFERS 2
|
#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_POWERUP_DELAY_SECONDS 6
|
||||||
#define LINKBUS_MIN_TX_INTERVAL_MS 100
|
|
||||||
|
#define LINKBUS_MIN_TX_INTERVAL_MS 100
|
||||||
//#define FOSC 8000000 /* Clock Speed */
|
|
||||||
#define FOSC 16000000 /* Clock Speed */
|
#define FOSC 16000000 /* Clock Speed */
|
||||||
#define BAUD 9600
|
#define BAUD 57600
|
||||||
//#define BAUD 19200
|
#define MYUBRR(b) (FOSC / 16 / (b) - 1)
|
||||||
#define MYUBRR(b) (FOSC / 16 / (b) - 1)
|
|
||||||
|
typedef enum
|
||||||
typedef enum
|
{
|
||||||
{
|
EMPTY_BUFF,
|
||||||
EMPTY_BUFF,
|
FULL_BUFF
|
||||||
FULL_BUFF
|
} BufferState;
|
||||||
} BufferState;
|
|
||||||
|
/* Linkbus Messages
|
||||||
/* Linkbus Messages
|
* Message formats:
|
||||||
* Message formats:
|
* $id,f1,f2... fn;
|
||||||
* $id,f1,f2... fn;
|
* !id,f1,f2,... fn;
|
||||||
* !id,f1,f2,... fn;
|
* $id,f1,f2,... fn?
|
||||||
* $id,f1,f2,... fn?
|
*
|
||||||
*
|
* where
|
||||||
* where
|
* $ = command - ! indicates a response or broadcast to subscribers
|
||||||
* $ = command - ! indicates a response or broadcast to subscribers
|
* id = linkbus MessageID
|
||||||
* id = linkbus MessageID
|
* fn = variable length fields
|
||||||
* fn = variable length fields
|
* ; = end of message flag - ? = end of query
|
||||||
* ; = end of message flag - ? = end of query
|
* Null fields in settings commands indicates no change should be applied
|
||||||
* Null fields in settings commands indicates no change should be applied
|
* All null fields indicates a polling request for current settings
|
||||||
* All null fields indicates a polling request for current settings
|
* ? terminator indicates subscription request to value changes
|
||||||
* ? terminator indicates subscription request to value changes
|
* Sending a query with fields containing data, is the equivalent of sending
|
||||||
* Sending a query with fields containing data, is the equivalent of sending
|
* a command followed by a query (i.e., a response is requested).
|
||||||
* a command followed by a query (i.e., a response is requested).
|
*
|
||||||
*
|
* TEST EQUIPMENT MESSAGE FAMILY (DEVICE MESSAGING)
|
||||||
* TEST EQUIPMENT MESSAGE FAMILY (DEVICE MESSAGING)
|
* $TST - Test message
|
||||||
* $TST - Test message
|
* !ACK - Simple acknowledgment to a command (sent when required)
|
||||||
* !ACK - Simple acknowledgment to a command (sent when required)
|
* $CK0 - Set Si5351 CLK0: field1 = freq (Hz); field2 = enable (BOOL)
|
||||||
* $CK0 - Set Si5351 CLK0: field1 = freq (Hz); field2 = enable (BOOL)
|
* $CK1 - Set Si5351 CLK1: 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)
|
||||||
* $CK2 - Set Si5351 CLK2: field1 = freq (Hz); field2 = enable (BOOL)
|
* $VOL - Set audio volume: field1 = inc/decr (BOOL); field2 = % (int)
|
||||||
* $VOL - Set audio volume: field1 = inc/decr (BOOL); field2 = % (int)
|
* $BAT? - Subscribe to battery voltage reports
|
||||||
* $BAT? - Subscribe to battery voltage reports
|
*
|
||||||
*
|
* DUAL-BAND RX MESSAGE FAMILY (FUNCTIONAL MESSAGING)
|
||||||
* DUAL-BAND RX MESSAGE FAMILY (FUNCTIONAL MESSAGING)
|
* $BND - Set/Get radio band to 2m or 80m
|
||||||
* $BND - Set/Get radio band to 2m or 80m
|
* $S? - Subscribe to signal strength reports
|
||||||
* $S? - Subscribe to signal strength reports
|
* - Subscribe to gain setting reports
|
||||||
* - Subscribe to gain setting reports
|
* -
|
||||||
* -
|
*/
|
||||||
*/
|
|
||||||
|
typedef enum
|
||||||
typedef enum
|
{
|
||||||
{
|
MESSAGE_EMPTY = 0,
|
||||||
MESSAGE_EMPTY = 0,
|
|
||||||
|
/* TEST EQUIPMENT MESSAGE FAMILY (TEST DEVICE MESSAGING) */
|
||||||
/* TEST EQUIPMENT MESSAGE FAMILY (TEST DEVICE MESSAGING) */
|
MESSAGE_BAND = 'B' * 100 + 'N' * 10 + 'D', /* $BND,; / $BND? / !BND,; // Set band; field1 = RadioBand */
|
||||||
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.) */
|
||||||
MESSAGE_TTY = 'T' * 100 + 'T' * 10 + 'Y', /* Adjust for PC communications interface (add crlf, etc.) */
|
|
||||||
|
/* DUAL-BAND TX MESSAGE FAMILY (FUNCTIONAL MESSAGING) */
|
||||||
/* DUAL-BAND TX MESSAGE FAMILY (FUNCTIONAL MESSAGING) */
|
MESSAGE_CLOCK_CAL = 'C' * 100 + 'A' * 10 + 'L', /* Set Jerry's clock calibration value */
|
||||||
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_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_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_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_CLOCK = 'T' * 100 + 'I' * 10 + 'M', /* Sets/reads the real-time clock */
|
MESSAGE_TEMP = 'T' * 100 + 'E' * 10 + 'M', /* Temperature data */
|
||||||
MESSAGE_STARTFINISH = 'S' * 10 + 'F', /* Sets the start and finish times */
|
MESSAGE_SET_STATION_ID = 'I' * 10 + 'D', /* Sets amateur radio callsign text */
|
||||||
MESSAGE_BAT = 'B' * 100 + 'A' * 10 + 'T', /* Battery charge data */
|
MESSAGE_GO = 'G' * 10 + 'O', /* Synchronizes clock */
|
||||||
MESSAGE_TEMP = 'T' * 100 + 'E' * 10 + 'M', /* Temperature data */
|
|
||||||
MESSAGE_PERM = 'P' * 100 + 'R' * 10 + 'M', /* Saves most settings to EEPROM "perm" */
|
/* UTILITY MESSAGES */
|
||||||
MESSAGE_TX_POWER = 'P' * 100 + 'O' * 10 + 'W', /* Sets transmit power level */
|
MESSAGE_RESET = 'R' * 100 + 'S' * 10 + 'T', /* Processor reset */
|
||||||
MESSAGE_TX_MOD = 'M' * 100 + 'O' * 10 + 'D', /* Sets 2m modulation format to AM or CW */
|
MESSAGE_VERSION = 'V' * 100 + 'E' * 10 + + 'R', /* S/W version number */
|
||||||
#ifdef DONOTUSE
|
|
||||||
MESSAGE_DRIVE_LEVEL = 'D' * 100 + 'R' * 10 + 'I', /* Adjust 2m drive level */
|
INVALID_MESSAGE = UINT16_MAX /* This value must never overlap a valid message ID */
|
||||||
#endif // DONOTUSE
|
} LBMessageID;
|
||||||
MESSAGE_SET_STATION_ID = 'I' * 10 + 'D', /* Sets amateur radio callsign text */
|
|
||||||
MESSAGE_SET_PATTERN = 'P' * 10 + 'A', /* Sets unique transmit pattern */
|
typedef enum
|
||||||
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 */
|
LINKBUS_MSG_UNKNOWN = 0,
|
||||||
MESSAGE_ESP_COMM = 'E' * 100 + 'S' * 10 + 'P', /* Communications with ESP8266 controller */
|
LINKBUS_MSG_COMMAND,
|
||||||
MESSAGE_GO = 'G' * 10 + 'O', /* Start transmitting now without delay */
|
LINKBUS_MSG_QUERY,
|
||||||
|
LINKBUS_MSG_REPLY,
|
||||||
/* UTILITY MESSAGES */
|
LINKBUS_MSG_INVALID
|
||||||
MESSAGE_RESET = 'R' * 100 + 'S' * 10 + 'T', /* Processor reset */
|
} LBMessageType;
|
||||||
MESSAGE_WIFI = 'W' * 10 + 'I', /* Enable/disable WiFi */
|
|
||||||
|
typedef enum
|
||||||
INVALID_MESSAGE = UINT16_MAX /* This value must never overlap a valid message ID */
|
{
|
||||||
} LBMessageID;
|
FIELD1 = 0,
|
||||||
|
FIELD2 = 1,
|
||||||
#define MESSAGE_CLOCK_LABEL "TIM"
|
FIELD3 = 2
|
||||||
#define MESSAGE_ESP_LABEL "ESP"
|
} LBMessageField;
|
||||||
#define MESSAGE_ERRORCODE_LABEL "EC"
|
|
||||||
#define MESSAGE_STATUSCODE_LABEL "SC"
|
typedef enum
|
||||||
#define MESSAGE_BAND_LABEL "BND"
|
{
|
||||||
#define MESSAGE_TX_POWER_LABEL "POW"
|
BATTERY_BROADCAST = 0x0001,
|
||||||
#define MESSAGE_ACK "!ACK;"
|
RSSI_BROADCAST = 0x0002,
|
||||||
|
RF_BROADCAST = 0x0004,
|
||||||
typedef enum
|
UPC_TEMP_BROADCAST = 0x0008,
|
||||||
{
|
ALL_BROADCASTS = 0x000FF
|
||||||
LINKBUS_MSG_UNKNOWN = 0,
|
} LBbroadcastType;
|
||||||
LINKBUS_MSG_COMMAND,
|
|
||||||
LINKBUS_MSG_QUERY,
|
typedef enum
|
||||||
LINKBUS_MSG_REPLY,
|
{
|
||||||
LINKBUS_MSG_INVALID
|
NO_ID = 0,
|
||||||
} LBMessageType;
|
CONTROL_HEAD_ID = 1,
|
||||||
|
RECEIVER_ID = 2,
|
||||||
typedef enum
|
TRANSMITTER_ID = 3
|
||||||
{
|
} DeviceID;
|
||||||
FIELD1 = 0,
|
|
||||||
FIELD2 = 1,
|
typedef char LinkbusTxBuffer[LINKBUS_MAX_TX_MSG_LENGTH];
|
||||||
FIELD3 = 2
|
|
||||||
} LBMessageField;
|
typedef struct
|
||||||
|
{
|
||||||
typedef enum
|
LBMessageType type;
|
||||||
{
|
LBMessageID id;
|
||||||
BATTERY_BROADCAST = 0x0001,
|
char fields[LINKBUS_MAX_MSG_NUMBER_OF_FIELDS][LINKBUS_MAX_MSG_FIELD_LENGTH];
|
||||||
RSSI_BROADCAST = 0x0002,
|
} LinkbusRxBuffer;
|
||||||
RF_BROADCAST = 0x0004,
|
|
||||||
UPC_TEMP_BROADCAST = 0x0008,
|
#define WAITING_FOR_UPDATE -1
|
||||||
ALL_BROADCASTS = 0x000FF
|
|
||||||
} LBbroadcastType;
|
/**
|
||||||
|
*/
|
||||||
typedef enum
|
void linkbus_init(uint32_t baud);
|
||||||
{
|
|
||||||
NO_ID = 0,
|
/**
|
||||||
CONTROL_HEAD_ID = 1,
|
* Immediately turns off receiver and flushes receive buffer
|
||||||
RECEIVER_ID = 2,
|
*/
|
||||||
TRANSMITTER_ID = 3
|
void linkbus_disable(void);
|
||||||
} DeviceID;
|
|
||||||
|
/**
|
||||||
typedef char LinkbusTxBuffer[LINKBUS_MAX_MSG_LENGTH];
|
* Undoes linkbus_disable()
|
||||||
|
*/
|
||||||
typedef struct
|
void linkbus_enable(void);
|
||||||
{
|
|
||||||
LBMessageType type;
|
|
||||||
LBMessageID id;
|
/**
|
||||||
char fields[LINKBUS_MAX_MSG_NUMBER_OF_FIELDS][LINKBUS_MAX_MSG_FIELD_LENGTH];
|
*/
|
||||||
} LinkbusRxBuffer;
|
void linkbus_end_tx(void);
|
||||||
|
|
||||||
#define WAITING_FOR_UPDATE -1
|
/**
|
||||||
|
*/
|
||||||
/**
|
void linkbus_reset_rx(void);
|
||||||
*/
|
|
||||||
void linkbus_init(uint32_t baud);
|
/**
|
||||||
|
*/
|
||||||
/**
|
LinkbusTxBuffer* nextEmptyTxBuffer(void);
|
||||||
* Immediately turns off receiver and flushes receive buffer
|
|
||||||
*/
|
/**
|
||||||
void linkbus_disable(void);
|
*/
|
||||||
|
LinkbusTxBuffer* nextFullTxBuffer(void);
|
||||||
/**
|
|
||||||
* Undoes linkbus_disable()
|
/**
|
||||||
*/
|
*/
|
||||||
void linkbus_enable(void);
|
BOOL linkbusTxInProgress(void);
|
||||||
|
|
||||||
|
/**
|
||||||
/**
|
*/
|
||||||
*/
|
LinkbusRxBuffer* nextEmptyRxBuffer(void);
|
||||||
void linkbus_end_tx(void);
|
|
||||||
|
/**
|
||||||
/**
|
*/
|
||||||
*/
|
LinkbusRxBuffer* nextFullRxBuffer(void);
|
||||||
void linkbus_reset_rx(void);
|
|
||||||
|
/**
|
||||||
/**
|
*/
|
||||||
*/
|
void lb_send_sync(void);
|
||||||
LinkbusTxBuffer* nextEmptyTxBuffer(void);
|
|
||||||
|
/**
|
||||||
/**
|
*/
|
||||||
*/
|
BOOL linkbus_send_text(char* text);
|
||||||
LinkbusTxBuffer* nextFullTxBuffer(void);
|
|
||||||
|
/**
|
||||||
/**
|
*/
|
||||||
*/
|
void lb_send_ESP(LBMessageType msgType, char* msg);
|
||||||
BOOL linkbusTxInProgress(void);
|
|
||||||
|
/**
|
||||||
/**
|
*/
|
||||||
*/
|
void lb_send_msg(LBMessageType msgType, char* msgLabel, char* msgStr);
|
||||||
LinkbusRxBuffer* nextEmptyRxBuffer(void);
|
|
||||||
|
/**
|
||||||
/**
|
*/
|
||||||
*/
|
void lb_broadcast_num(uint16_t data, char* str);
|
||||||
LinkbusRxBuffer* nextFullRxBuffer(void);
|
|
||||||
|
/**
|
||||||
/**
|
*/
|
||||||
*/
|
void lb_send_Help(void);
|
||||||
void lb_send_sync(void);
|
|
||||||
|
/**
|
||||||
/**
|
*/
|
||||||
*/
|
void lb_send_NewPrompt(void);
|
||||||
BOOL linkbus_send_text(char* text);
|
|
||||||
|
/**
|
||||||
/**
|
*/
|
||||||
*/
|
void lb_send_NewLine(void);
|
||||||
void lb_send_ESP(LBMessageType msgType, char* msg);
|
|
||||||
|
/**
|
||||||
/**
|
*/
|
||||||
*/
|
void linkbus_setLineTerm(char* term);
|
||||||
void lb_send_msg(LBMessageType msgType, char* msgLabel, char* msgStr);
|
|
||||||
|
/**
|
||||||
/**
|
*/
|
||||||
*/
|
void lb_echo_char(uint8_t c);
|
||||||
void lb_broadcast_num(uint16_t data, char* str);
|
|
||||||
|
/**
|
||||||
/**
|
*/
|
||||||
*/
|
BOOL lb_send_string(char* str);
|
||||||
void lb_send_Help(void);
|
|
||||||
|
/**
|
||||||
#endif /* LINKBUS_H_ */
|
*/
|
||||||
|
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