diff --git a/include/aprsis.h b/include/aprsis.h index e483bf9..3f19cf9 100644 --- a/include/aprsis.h +++ b/include/aprsis.h @@ -13,6 +13,7 @@ #include "gsm/sim800c_tcpip.h" #include "ax25.h" #include "telemetry.h" +#include "message.h" typedef enum aprsis_return { @@ -99,8 +100,11 @@ void aprsis_igate_to_aprsis(AX25Msg *msg, const char * callsign_with_ssid); void aprsis_send_server_comm_counters(const char * callsign_with_ssid); void aprsis_send_loginstring(const char * callsign_with_ssid, uint8_t rtc_ok, uint16_t voltage); void aprsis_send_gsm_status(const char * callsign_with_ssid); +void aprsis_send_ack_for_message(const message_t * const message); +#ifdef UNIT_TEST char * aprsis_get_tx_buffer(void); +#endif uint8_t aprsis_get_aprsis_logged(void); void aprsis_debug_set_simulate_timeout(void); diff --git a/include/backup_registers.h b/include/backup_registers.h index 9357292..2e20795 100644 --- a/include/backup_registers.h +++ b/include/backup_registers.h @@ -44,6 +44,14 @@ inline uint32_t backup_reg_get_monitor(void) { return REGISTER_MONITOR; } +#define BACKUP_REG_ASSERT_CONCURENT_ACCES_APRSIS_WX (1U) +#define BACKUP_REG_ASSERT_CONCURENT_ACCES_APRSIS_BEACON (1U << 1U) +#define BACKUP_REG_ASSERT_CONCURENT_ACCES_APRSIS_TELEMETRY (1U << 2U) +#define BACKUP_REG_ASSERT_CONCURENT_ACCES_APRSIS_DESCR (1U << 3U) +#define BACKUP_REG_ASSERT_CONCURENT_ACCES_APRSIS_IGATE (1U << 4U) +#define BACKUP_REG_ASSERT_CONCURENT_ACCES_APRSIS_CNTRS (1U << 5U) +#define BACKUP_REG_ASSERT_CONCURENT_ACCES_APRSIS_LOGINSTRING (1U << 6U) + uint32_t backup_reg_get_configuration(void); void backup_reg_set_configuration(uint32_t value); void backup_reg_set_bits_configuration(uint32_t value); @@ -86,6 +94,7 @@ void backup_reg_increment_weather_measurements_check_reset(void); void backup_reg_increment_dallas_degraded_reset(void); void backup_reg_increment_is_rtc_ok_check_reset(void); +void backup_assert(uint32_t assert); #endif /* BACKUP_REGISTERS_H_ */ diff --git a/include/rte_main.h b/include/rte_main.h index 49ce2a9..705202c 100644 --- a/include/rte_main.h +++ b/include/rte_main.h @@ -4,6 +4,7 @@ #include #include "stored_configuration_nvm/config_data.h" +#include "message.h" //!< Set immediately after waking up in RTC interrupt handler #define RTE_MAIN_WOKEN_UP_RTC_INTERRUPT 1u @@ -14,6 +15,12 @@ //!< Set after everything was reinitialized from #define RTE_MAIN_WOKEN_UP_EXITED 4u +extern message_t rte_main_received_message; +extern message_source_t rte_main_received_message_source; + +//!< Trigger preparing and sending ACK +extern uint8_t rte_main_trigger_message_ack; + extern uint8_t rte_main_trigger_gsm_aprsis_counters_packet; extern uint8_t rte_main_trigger_gsm_loginstring_packet; diff --git a/src/aprsis.c b/src/aprsis.c index 52cfccc..1aa2a7f 100644 --- a/src/aprsis.c +++ b/src/aprsis.c @@ -8,6 +8,8 @@ #include "aprsis.h" #include "etc/aprsis_config.h" #include "text.h" +#include "backup_registers.h" + #include "aprs/status.h" #include "aprs/message.h" @@ -41,7 +43,7 @@ gsm_sim800_state_t * aprsis_gsm_modem_state; /** * Buffer for sending packet to aprs-is */ -char aprsis_packet_tx_buffer[APRSIS_TX_BUFFER_LN]; +static char aprsis_packet_tx_buffer[APRSIS_TX_BUFFER_LN]; /** * Lenght of buffer @@ -81,6 +83,16 @@ const char * aprsis_default_server_address; */ const char * aprsis_callsign_with_ssid; +/** + * Pointer to callsign from configuration + */ +const char * aprsis_callsign; + +/** + * ssid from configuration + */ +uint8_t aprsis_ssid; + /** * Lenght of APRS-IS server address string */ @@ -193,13 +205,13 @@ char aprsis_login_string_reveived[APRSIS_LOGIN_STRING_RECEIVED_LN]; * @param message_ln * @return position at which content of message starts */ -STATIC int aprsis_check_is_message(const uint8_t * const message, const uint16_t message_ln) { +STATIC uint16_t aprsis_check_is_message(const uint8_t * const message, const uint16_t message_ln) { // example message // Details:"SP8EBC>APX216,TCPIP*,qAC,NINTH::SR9WXZ :tedt{0s}\r\n", '\0' // go through a buffer and look for double ':' - int message_start_position = 0; + uint16_t message_start_position = 0; for (int i = 0; i < message_ln; i++) { const uint8_t * this_character = message + i; @@ -233,18 +245,46 @@ STATIC void aprsis_receive_callback(srl_context_t* srl_context) { if (srl_context->srl_rx_state == SRL_RX_DONE) { // check if this is keepalive message if (*buffer == '#') { + // set last timestamps aprsis_last_keepalive_ts = main_get_master_time(); - aprsis_last_keepalive_long_ts = main_get_master_time(); + // increase received keepalive counter aprsis_keepalive_received_counter++; + // restart receiving from serial port gsm_sim800_tcpip_async_receive(aprsis_serial_port, aprsis_gsm_modem_state, 0, 61000, aprsis_receive_callback); - } - else if (aprsis_check_is_message(buffer, message_ln) == 1) { - } else { + // check if this is an aprs message + const int message_position = aprsis_check_is_message(buffer, message_ln); + + // if yes try to decode it + if (message_position != 0) { + + // prevent overwriting message received from radio channel if it hasn't been serviced yet + if (rte_main_received_message_source == MESSAGE_SOURCE_UNINITIALIZED) { + + // if decoding was successfull + if (message_decode(buffer, message_ln, message_position, MESSAGE_SOURCE_APRSIS, &rte_main_received_message) == 0) { + + // check if it is for me + if (message_is_for_me(aprsis_callsign, aprsis_ssid, &rte_main_received_message) == 0) { + // set a source of this message + rte_main_received_message_source = MESSAGE_SOURCE_APRSIS; + + // trigger preparing ACK + rte_main_trigger_message_ack = 1; + } + + + } + } + } + else { + ; + } + aprsis_another_received_counter++; gsm_sim800_tcpip_async_receive(aprsis_serial_port, aprsis_gsm_modem_state, 0, 61000, aprsis_receive_callback); @@ -253,6 +293,18 @@ STATIC void aprsis_receive_callback(srl_context_t* srl_context) { } } +/** + * + * @param context + * @param gsm_modem_state + * @param callsign + * @param ssid + * @param passcode + * @param default_server + * @param default_port + * @param reset_on_timeout + * @param callsign_with_ssid + */ void aprsis_init( srl_context_t * context, gsm_sim800_state_t * gsm_modem_state, @@ -285,6 +337,10 @@ void aprsis_init( aprsis_reset_on_timeout = reset_on_timeout; + aprsis_callsign = callsign; + + aprsis_ssid = ssid; + } /** @@ -574,6 +630,11 @@ void aprsis_send_wx_frame( return; } + if (gsm_sim800_tcpip_tx_busy() == 1) { + // will die here + backup_assert(BACKUP_REG_ASSERT_CONCURENT_ACCES_APRSIS_WX); + } + aprsis_tx_counter++; float max_wind_speed = 0.0f, temp = 0.0f; @@ -652,6 +713,11 @@ void aprsis_send_beacon( return; } + if (gsm_sim800_tcpip_tx_busy() == 1) { + // will die here + backup_assert(BACKUP_REG_ASSERT_CONCURENT_ACCES_APRSIS_BEACON); + } + aprsis_tx_counter++; aprsis_packet_tx_message_size = snprintf( @@ -771,6 +837,8 @@ void aprsis_prepare_telemetry( /** * Sends to APRS-IS prepared telemetry frame prepared in advance + * @param async + * @param callsign_with_ssid */ void aprsis_send_telemetry(uint8_t async, const char * callsign_with_ssid) { @@ -784,6 +852,11 @@ void aprsis_send_telemetry(uint8_t async, const char * callsign_with_ssid) { return; } + if (gsm_sim800_tcpip_tx_busy() == 1) { + // will die here + backup_assert(BACKUP_REG_ASSERT_CONCURENT_ACCES_APRSIS_TELEMETRY); + } + aprsis_tx_counter++; aprsis_packet_tx_message_size = snprintf( @@ -843,6 +916,11 @@ telemetry_description_t aprsis_send_description_telemetry(uint8_t async, return next; } + if (gsm_sim800_tcpip_tx_busy() == 1) { + // will die here + backup_assert(BACKUP_REG_ASSERT_CONCURENT_ACCES_APRSIS_DESCR); + } + telemetry_create_description_string(config_basic, what, main_own_aprs_msg, OWN_APRS_MSG_LN); aprsis_tx_counter++; @@ -881,6 +959,11 @@ void aprsis_igate_to_aprsis(AX25Msg *msg, const char * callsign_with_ssid) { return; } + if (gsm_sim800_tcpip_tx_busy() == 1) { + // will die here + backup_assert(BACKUP_REG_ASSERT_CONCURENT_ACCES_APRSIS_IGATE); + } + aprsis_igated_counter++; // prepare buffer for message @@ -962,6 +1045,11 @@ void aprsis_send_server_comm_counters(const char * callsign_with_ssid) { return; } + if (gsm_sim800_tcpip_tx_busy() == 1) { + // will die here + backup_assert(BACKUP_REG_ASSERT_CONCURENT_ACCES_APRSIS_CNTRS); + } + memset (aprsis_packet_tx_buffer, 0x00, APRSIS_TX_BUFFER_LN); aprsis_tx_counter++; @@ -988,6 +1076,11 @@ void aprsis_send_loginstring(const char * callsign_with_ssid, uint8_t rtc_ok, ui return; } + if (gsm_sim800_tcpip_tx_busy() == 1) { + // will die here + backup_assert(BACKUP_REG_ASSERT_CONCURENT_ACCES_APRSIS_LOGINSTRING); + } + memset (aprsis_packet_tx_buffer, 0x00, APRSIS_TX_BUFFER_LN); aprsis_tx_counter++; @@ -1029,9 +1122,24 @@ void aprsis_send_gsm_status(const char * callsign_with_ssid) { gsm_sim800_tcpip_async_write((uint8_t *)aprsis_packet_tx_buffer, aprsis_packet_tx_message_size, aprsis_serial_port, aprsis_gsm_modem_state); } +/** + * + * @param message + */ +void aprsis_send_ack_for_message(const message_t * const message) { + aprsis_packet_tx_message_size = message_create_ack_for((uint8_t*)aprsis_packet_tx_buffer, APRSIS_TX_BUFFER_LN - 1, message, MESSAGE_SOURCE_APRSIS); + + gsm_sim800_tcpip_async_write((uint8_t *)aprsis_packet_tx_buffer, aprsis_packet_tx_message_size, aprsis_serial_port, aprsis_gsm_modem_state); + + rte_main_received_message_source = MESSAGE_SOURCE_UNINITIALIZED; + +} + +#ifdef UNIT_TEST char * aprsis_get_tx_buffer(void) { return aprsis_packet_tx_buffer; } +#endif uint8_t aprsis_get_aprsis_logged(void) { return aprsis_logged; diff --git a/src/backup_registers.c b/src/backup_registers.c index 665d07d..62731a3 100644 --- a/src/backup_registers.c +++ b/src/backup_registers.c @@ -17,11 +17,13 @@ #define REGISTER_LAST_SLTIM RTC->BKP6R #define REGISTER_PACKET_COUNTERS RTC->BKP7R #define REGISTER_RESET_CHECK_FAIL RTC->BKP8R +#define REGISTER_ASSERT RTC->BKP9R #endif #define BACKUP_REG_INHIBIT_PWR_SWITCH_PERIODIC_H 1u #define BACKUP_REG_ALL_PWRSAVE_STATES_BITMASK (0xFFu << 2) + // backup registers (ParaTNC) // 0 -> // 2 -> boot and hard fault count @@ -41,6 +43,7 @@ // 6 -> last sleep time // 7 -> weather and telemetry timers & counters // 8 -> counters of resets caused by validation checks failures +// 9 -> assert register // 7th register map // xxxxyyAA - telemetry frames counter @@ -597,6 +600,7 @@ void backup_reg_set_packet_counters(uint8_t beacon_counter, uint8_t meteo_counte } void backup_reg_increment_aprsis_check_reset(void) { +#ifdef PARAMETEO // REGISTER_RESET_CHECK_FAIL volatile uint32_t reg_value = REGISTER_RESET_CHECK_FAIL; @@ -617,9 +621,11 @@ void backup_reg_increment_aprsis_check_reset(void) { REGISTER_RESET_CHECK_FAIL = reg_value; backup_reg_lock(); +#endif } void backup_reg_increment_weather_measurements_check_reset(void) { +#ifdef PARAMETEO // REGISTER_RESET_CHECK_FAIL volatile uint32_t reg_value = REGISTER_RESET_CHECK_FAIL; @@ -640,9 +646,11 @@ void backup_reg_increment_weather_measurements_check_reset(void) { REGISTER_RESET_CHECK_FAIL = reg_value; backup_reg_lock(); +#endif } void backup_reg_increment_dallas_degraded_reset(void) { +#ifdef PARAMETEO // REGISTER_RESET_CHECK_FAIL volatile uint32_t reg_value = REGISTER_RESET_CHECK_FAIL; @@ -663,9 +671,11 @@ void backup_reg_increment_dallas_degraded_reset(void) { REGISTER_RESET_CHECK_FAIL = reg_value; backup_reg_lock(); +#endif } void backup_reg_increment_is_rtc_ok_check_reset(void) { +#ifdef PARAMETEO // REGISTER_RESET_CHECK_FAIL volatile uint32_t reg_value = REGISTER_RESET_CHECK_FAIL; @@ -686,4 +696,17 @@ void backup_reg_increment_is_rtc_ok_check_reset(void) { REGISTER_RESET_CHECK_FAIL = reg_value; backup_reg_lock(); +#endif +} + +void backup_assert(uint32_t assert) { +#ifdef PARAMETEO + backup_reg_unclock(); + + REGISTER_ASSERT |= assert; + + backup_reg_lock(); + + NVIC_SystemReset(); +#endif } diff --git a/src/main.c b/src/main.c index 2516fdb..365d365 100644 --- a/src/main.c +++ b/src/main.c @@ -1246,14 +1246,27 @@ int main(int argc, char* argv[]){ // receive callback for communicatio with the modem gsm_sim800_rx_done_event_handler(main_gsm_srl_ctx_ptr, &main_gsm_state); - - //srl_reset(main_gsm_srl_ctx_ptr); } if (main_gsm_srl_ctx_ptr->srl_tx_state == SRL_TX_IDLE) { gsm_sim800_tx_done_event_handler(main_gsm_srl_ctx_ptr, &main_gsm_state); } + if (rte_main_trigger_message_ack == 1) { + if (rte_main_received_message_source == MESSAGE_SOURCE_APRSIS && gsm_sim800_tcpip_tx_busy() == 0) { + + rte_main_trigger_message_ack = 0; + + aprsis_send_ack_for_message(&rte_main_received_message); + + rte_main_received_message_source == MESSAGE_SOURCE_UNINITIALIZED; + } + else if (rte_main_received_message_source == MESSAGE_SOURCE_RADIO) { + + } + + } + if (rte_main_trigger_gsm_status == 1 && gsm_sim800_tcpip_tx_busy() == 0) { rte_main_trigger_gsm_status = 0; diff --git a/src/rte_main.c b/src/rte_main.c index 58c1e16..0101eba 100644 --- a/src/rte_main.c +++ b/src/rte_main.c @@ -17,7 +17,13 @@ uint8_t rte_main_trigger_status = 0; uint8_t rte_main_trigger_wx_packet = 0; +message_t rte_main_received_message; +message_source_t rte_main_received_message_source; + #ifdef PARAMETEO +//!< Trigger preparing and sending ACK +uint8_t rte_main_trigger_message_ack = 0; + uint8_t rte_main_trigger_gsm_aprsis_counters_packet = 0; //!< Trigger sending status packet with received APRS is login string diff --git a/src/variant_parameteo.c b/src/variant_parameteo.c index 5b42777..daa3687 100644 --- a/src/variant_parameteo.c +++ b/src/variant_parameteo.c @@ -25,7 +25,6 @@ int variant_validate_is_within_ram(void * address) { } int variant_validate_is_within_flash(void * address) { - uint32_t addr_value = (uint32_t)address; if (addr_value > FLASH_BASE && diff --git a/system/include/aprs/message.h b/system/include/aprs/message.h index e6e84de..88a1d3c 100644 --- a/system/include/aprs/message.h +++ b/system/include/aprs/message.h @@ -22,9 +22,11 @@ typedef struct message_t { }message_t; typedef enum message_source_t { - MESSAGE_SOURCE_APRSIS, - MESSAGE_SOURCE_RADIO - + MESSAGE_SOURCE_UNINITIALIZED = 0x0, + MESSAGE_SOURCE_APRSIS = 0x1, + MESSAGE_SOURCE_APRSIS_HEXCNTR = 0x2, + MESSAGE_SOURCE_RADIO = 0x11, + MESSAGE_SOURCE_RADIO_HEXCNTR = 0x12 }message_source_t; /** @@ -36,7 +38,7 @@ typedef enum message_source_t { * @param output parsed APRS message content * @return zero if message has been found and decoded, non zero if parsing failed */ -uint8_t message_decode_from_aprsis(const uint8_t * const message, const uint16_t message_ln, uint16_t content_position, message_source_t src, message_t * output); +uint8_t message_decode(const uint8_t * const message, const uint16_t message_ln, uint16_t content_position, message_source_t src, message_t * output); /** * @@ -44,7 +46,7 @@ uint8_t message_decode_from_aprsis(const uint8_t * const message, const uint16_t * @param message * @return zero if this is a message to us, non zero otherwise */ -uint8_t message_is_for_me(config_data_basic_t * config_data, const message_t * const message); +uint8_t message_is_for_me(const char * const callsign, const uint8_t ssid, const message_t * const message); /** * @@ -53,6 +55,6 @@ uint8_t message_is_for_me(config_data_basic_t * config_data, const message_t * c * @param message * @param src how this message has been received */ -void message_create_ack_for(uint8_t * out_buffer, const uint16_t out_buffer_ln, const message_t * const message, const message_source_t src); +int message_create_ack_for(uint8_t * out_buffer, const uint16_t out_buffer_ln, const message_t * const message, const message_source_t src); #endif /* INCLUDE_APRS_MESSAGE_H_ */ diff --git a/system/src/aprs/message.c b/system/src/aprs/message.c index 8d31fb2..29ea1a0 100644 --- a/system/src/aprs/message.c +++ b/system/src/aprs/message.c @@ -6,9 +6,16 @@ */ #include "message.h" +#include "variant.h" #include "string.h" #include "stdio.h" +#ifdef UNIT_TEST +#define STATIC +#else +#define STATIC static +#endif + #define MESSAGE_RECIPIENT_FIELD_SIZE 9 #define MESSAGE_SSID_CHARS_LN 2 @@ -27,8 +34,77 @@ #define MESSAGE_ACK_CURRENT_POS (char*)(out_buffer + current_pos) +/** + * Lookup table used to string-to-int conversion for HEX strings. Value of 0x30 should be + * subtracted from ASCII scancode and this value should be used to intex this table +*/ +static const int8_t message_atoi_lookup[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, + -1, -1, -1, -1, -1, -1, -1, + 10, 11, 12, 13, 14, 15, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + 10, 11, 12, 13, 14, 15}; + +/** + * Table used +*/ static char message_atoi_buffer[MESSAGE_ATOI_BUFFER]; +/** + * Convert string with message number to integer, with automatic detection of decimal or hex base. It operates + * only on positive integers up to 32 bit wide. + * @param string + * @param string_ln + * @param output optional pointer to message structure when output will be also put + * @return unsigned integer with decoded number + */ +STATIC uint32_t message_atoi_message_counter(const uint8_t const * string, uint8_t string_ln, message_t * output) { + + uint32_t sum = 0u; + + int8_t conversion_table[6]; + + int8_t is_hex = 0; + + if (variant_validate_is_within_ram(string) == 1 && string_ln <= 6) { + memset(conversion_table, 0x00, string_ln); + + for (int8_t i = string_ln; i >= 0; i--) { + const uint8_t index = *(string + i - 1) - 0x30u; + + conversion_table[string_ln - i] = message_atoi_lookup[index]; + + if (*(string + i) > '9') { + is_hex = 1; + } + } + + if (is_hex == 1) { + sum = (conversion_table[0]); + sum += (conversion_table[1] * 0x10); + sum += (conversion_table[2] * 0x100); + sum += (conversion_table[3] * 0x1000); + sum += (conversion_table[4] * 0x10000); + sum += (conversion_table[5] * 0x100000); + } + else { + sum = (conversion_table[0]); + sum += (conversion_table[1] * 10); + sum += (conversion_table[2] * 100); + sum += (conversion_table[3] * 1000); + sum += (conversion_table[4] * 10000); + sum += (conversion_table[5] * 100000); + } + } + + if (variant_validate_is_within_ram(output) == 1) { + output->number = sum & 0xFFu; + } + + return sum; +} + /** * Decode received data to look for an APRS message and put it into a structure * @param message pointer to data received from APRS-IS @@ -37,7 +113,7 @@ static char message_atoi_buffer[MESSAGE_ATOI_BUFFER]; * @param output parsed APRS message content * @return zero if message has been found and decoded, non zero if parsing failed */ -uint8_t message_decode_from_aprsis(const uint8_t * const message, const uint16_t message_ln, uint16_t content_position, message_source_t src, message_t * output) { +uint8_t message_decode(const uint8_t * const message, const uint16_t message_ln, uint16_t content_position, message_source_t src, message_t * output) { // example message:: SP8EBC>APX216,TCPIP*,qAC,NINTH::SR9WXZ :tedt{0s}\r\n @@ -271,11 +347,11 @@ uint8_t message_decode_from_aprsis(const uint8_t * const message, const uint16_t * @param message * @return zero if this is a message to us, non zero otherwise */ -uint8_t message_is_for_me(config_data_basic_t * config_data, const message_t * const message) +uint8_t message_is_for_me(const char * const callsign, const uint8_t ssid, const message_t * const message) { - const int callsign = strncmp(config_data->callsign, message->to.call, 6); + const int _callsign = strncmp(callsign, message->to.call, 6); - if (callsign == 0 && (config_data->ssid == message->to.ssid)) { + if (_callsign == 0 && (ssid == message->to.ssid)) { return 0; } else { @@ -290,7 +366,7 @@ uint8_t message_is_for_me(config_data_basic_t * config_data, const message_t * c * @param message * @param src how this message has been received */ -void message_create_ack_for(uint8_t * out_buffer, const uint16_t out_buffer_ln, const message_t * const message, const message_source_t src) +int message_create_ack_for(uint8_t * out_buffer, const uint16_t out_buffer_ln, const message_t * const message, const message_source_t src) { int current_pos = 0; @@ -352,10 +428,12 @@ void message_create_ack_for(uint8_t * out_buffer, const uint16_t out_buffer_ln, current_pos += 9; // then put 'ackXX' where X is message number - current_pos += snprintf(MESSAGE_ACK_CURRENT_POS, MESSAGE_ACK_REMAINING_BUF, ":ack%d", message->number); + current_pos += snprintf(MESSAGE_ACK_CURRENT_POS, MESSAGE_ACK_REMAINING_BUF, ":ack%d\r\n", message->number); } else { } + + return current_pos; }