Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 54 additions & 1 deletion Firmware/radio/at.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
#include "flash_layout.h"
#include "at.h"
#include "board.h"
#include "ham.h"

#ifdef INCLUDE_AES
#include "AES/aes.h"
Expand Down Expand Up @@ -70,6 +71,7 @@ static void at_m(void);

#pragma save
#pragma nooverlay

void
at_input(register uint8_t c)
{
Expand Down Expand Up @@ -458,7 +460,58 @@ at_ampersand(void)
break;
}
#endif // INCLUDE_AES
default:
case 'C':
switch (at_cmd[4]) {
case 'E':
// enables transmission of callsign (default every 10 minutes)
enable_callsign = true;
printf("Transmission of callsign enabled: %s\n",callsign);
break;
case 'D':
// disables transmission of callsign
enable_callsign = false;
printf("Transmission of callsign disabled: %s\n",callsign);
break;
case 'S':
// user is entering their callsign
// interval (in seconds) between transmission of callsign
// get the register number first
if(at_cmd[5] == '=')
{
register uint8_t c;
idx = 6;
uint8_t cs_idx = 0;
for (;;) {
c = at_cmd[idx];
// if (!isalnum(c))
if (!(isalpha(c) || isdigit(c)))
break;
callsign[cs_idx++] = c;
idx++;
}
printf("Callsign set to %s\n",callsign);
}
else
at_error();
break;
case 'I':
// interval (in seconds) between transmission of callsign
// get the register number first
if(at_cmd[5] == '=')
{
idx = 6;
at_parse_number();
// Max allowed interval is 10 minutes
callsign_tx_interval_secs = at_num < MAX_CALLSIGN_INTERVAL_SEC ? at_num : MAX_CALLSIGN_INTERVAL_SEC;
printf("Callsign transmission interval %d s\n",callsign_tx_interval_secs);
}
else
at_error();
break;
}
break;

default:
at_error();
break;
}
Expand Down
51 changes: 51 additions & 0 deletions Firmware/radio/ham.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// -*- Mode: C; c-basic-offset: 8; -*-
//
// Copyright (c) 2025 Alexis Nicole Benini, Ph.D.
// www.alexisbenini.com
// All Rights Reserved
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
// o Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// o Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in
// the documentation and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
// COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
// OF THE POSSIBILITY OF SUCH DAMAGE.
//

///
/// @file ham.c
///
/// Functions for transmission of HAM radio callsign
///

#include "ham.h"
#include <string.h>

__xdata char callsign[CALLSIGN_MAX_LENGTH];
__pdata uint16_t callsign_tx_interval_secs;
__pdata bool enable_callsign;

#pragma nooverlay

void initialize_ham_callsign_tx_params()
{
enable_callsign = false;
memcpy(callsign,"NOSIGN",7);
callsign_tx_interval_secs = 2; // 600;
}
53 changes: 53 additions & 0 deletions Firmware/radio/ham.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
// -*- Mode: C; c-basic-offset: 8; -*-
//
// Copyright (c) 2025 Alexis Nicole Benini, Ph.D.
// www.alexisbenini.com
// All Rights Reserved
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
// o Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// o Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in
// the documentation and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
// COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
// OF THE POSSIBILITY OF SUCH DAMAGE.
//

///
/// @file ham.h
///
/// Function and parameters for transmission of HAM radio callsign
///

#ifndef _HAM_H_
#define _HAM_H_

#include <stdint.h>
#include <stdbool.h>
#include "cdt.h"

#define MAX_CALLSIGN_INTERVAL_SEC 10*60 // According to FCC rules, the call sign must be transmitted at least every 10 minutes.
#define CALLSIGN_MAX_LENGTH 8 // This includes the initial "DE" sequence
extern __xdata char callsign[CALLSIGN_MAX_LENGTH]; // This assumes that the operator is using a standard callsign length (6).
// However, some regions might use 7 characters. The length of this array includes also the \0 at the end
extern __pdata uint16_t callsign_tx_interval_secs; // This is set to 600 seconds (10 minutes) by default
extern __pdata bool enable_callsign; // Set to false by default (no callsign transmission)

void initialize_ham_callsign_tx_params();

#endif // _HAM_H_
4 changes: 4 additions & 0 deletions Firmware/radio/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
#include "tdm.h"
#include "timer.h"
#include "freq_hopping.h"
#include "ham.h"

#ifdef INCLUDE_AES
#include "AES/aes.h"
Expand Down Expand Up @@ -129,6 +130,9 @@ main(void)
// do radio initialisation
radio_init();

// ham radio callsign initialization
initialize_ham_callsign_tx_params();

// turn on the receiver
if (!radio_receiver_on()) {
panic("failed to enable receiver");
Expand Down
64 changes: 45 additions & 19 deletions Firmware/radio/tdm.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
#include "freq_hopping.h"
#include "crc.h"
#include "serial.h"
#include "ham.h"

#ifdef INCLUDE_AES
#include "AES/aes.h"
Expand Down Expand Up @@ -139,6 +140,7 @@ static __bit send_statistics;
/// set when we should send a MAVLink report pkt
extern uint8_t seen_mavlink;


struct tdm_trailer {
uint16_t window:13;
uint16_t command:1;
Expand All @@ -156,6 +158,7 @@ static __pdata char remote_at_cmd[AT_CMD_MAXLEN + 1];

#define PACKET_OVERHEAD (sizeof(trailer)+16)


/// display RSSI output
///
void
Expand Down Expand Up @@ -495,6 +498,7 @@ handle_at_command(__pdata uint8_t len)
// a stack carary to detect a stack overflow
__at(0xFF) uint8_t __idata _canary;


/// main loop for time division multiplexing transparent serial
///
void
Expand All @@ -516,9 +520,13 @@ tdm_serial_loop(void)
__pdata uint16_t last_t = timer2_tick();
__pdata uint16_t last_link_update = last_t;

__pdata uint16_t half_seconds = 0;
__pdata bool tx_callsign = false;

_canary = 42;

uint8_t counter = 0;

for (;;) {
if (_canary != 42) {
panic("stack blown\n");
Expand Down Expand Up @@ -627,7 +635,7 @@ tdm_serial_loop(void)
}
continue;
}

// see how many 16usec ticks have passed and update
// the tdm state machine. We re-fetch tnow as a bad
// packet could have cost us a lot of time.
Expand All @@ -640,8 +648,15 @@ tdm_serial_loop(void)
if (tnow - last_link_update > 32768) {
link_update();
last_link_update = tnow;
half_seconds++;
}

// enable transmission of callsign
if(enable_callsign && half_seconds/2 > callsign_tx_interval_secs)
{
tx_callsign = true;
half_seconds = 0;
}

if (lbt_rssi != 0) {
// implement listen before talk
Expand Down Expand Up @@ -738,26 +753,37 @@ tdm_serial_loop(void)
pins_user_check();
#endif

// ask the packet system for the next packet to send
if (send_at_command &&
max_xmit >= strlen(remote_at_cmd)) {
// send a remote AT command
len = strlen(remote_at_cmd);
memcpy(pbuf, remote_at_cmd, len);
trailer.command = 1;
send_at_command = false;
} else {
// get a packet from the serial port
len = packet_get_next(max_xmit, pbuf);

if (len > 0) {
trailer.command = packet_is_injected();
} else {
trailer.command = 0;
}
if(tx_callsign)
{
len = 7;
// printf("time to send: %s\n",callsign);
memcpy(pbuf,callsign, 7);
trailer.command = 1;
tx_callsign = false;
}
else
{
// ask the packet system for the next packet to send
if (send_at_command &&
max_xmit >= strlen(remote_at_cmd)) {
// send a remote AT command
len = strlen(remote_at_cmd);
memcpy(pbuf, remote_at_cmd, len);
trailer.command = 1;
send_at_command = false;
} else {
// get a packet from the serial port
len = packet_get_next(max_xmit, pbuf);

if (len > 0) {
trailer.command = packet_is_injected();
} else {
trailer.command = 0;
}
#ifdef INCLUDE_AES
trailer.crc = crc16(len, pbuf);
trailer.crc = crc16(len, pbuf);
#endif
}
}

if (len > max_data_packet_length) {
Expand Down