14 int16_t state = ERR_NONE;
15 FOSSASAT_DEBUG_WRITE(modem);
22 LORA_SPREADING_FACTOR,
40 radio.setSyncWord(syncWordFSK, 2);
52 FOSSASAT_DEBUG_PRINT(F(
"Init "));
53 FOSSASAT_DEBUG_PRINTLN(state);
54 FOSSASAT_DEBUG_DELAY(10);
55 if (state != ERR_NONE) {
72 uint8_t sfs[] = {LORA_SPREADING_FACTOR, LORA_SPREADING_FACTOR_ALT};
76 return(ERR_WRONG_MODEM);
80 int16_t state =
radio.setSpreadingFactor(sfs[sfMode]);
83 if(state == ERR_NONE) {
93 return(ERR_PACKET_TOO_LONG);
98 return(ERR_INVALID_BANDWIDTH);
102 float bws[] = {7.8, 10.4, 15.6, 20.8, 31.25, 41.7, 62.5, 125.0};
103 uint16_t preambleLength = 0;
104 memcpy(&preambleLength, optData + 3,
sizeof(uint16_t));
113 if(state != ERR_NONE) {
118 state =
radio.setCRC(optData[5]);
138 for(uint8_t i = 0; i < callsignLen - 1; i++) {
139 morse.print(callsign[i]);
154 radio.transmitDirect();
161 static const uint8_t optDataLen = 6*
sizeof(uint8_t) + 3*
sizeof(int16_t) +
sizeof(uint16_t) +
sizeof(int8_t) +
sizeof(uint32_t);
162 uint8_t optData[optDataLen];
163 uint8_t* optDataPtr = optData;
168 uint8_t batteryVoltage = 4.02 * (VOLTAGE_UNIT / VOLTAGE_MULTIPLIER);
170 Communication_Frame_Add<uint8_t>(&optDataPtr, batteryVoltage,
"batV");
176 int16_t batteryChargingCurrent = 0.056 * (CURRENT_UNIT / CURRENT_MULTIPLIER);
178 Communication_Frame_Add<int16_t>(&optDataPtr, batteryChargingCurrent,
"batChI");
184 uint8_t batteryChargingVoltage = 3.82 * (VOLTAGE_UNIT / VOLTAGE_MULTIPLIER);
186 Communication_Frame_Add<uint8_t>(&optDataPtr, batteryChargingVoltage,
"batChV");
196 memcpy(optDataPtr, &
powerConfig.val,
sizeof(uint8_t));
197 optDataPtr +=
sizeof(uint8_t);
204 Communication_Frame_Add<uint8_t>(&optDataPtr, solarCellAVoltage,
"sAV");
209 Communication_Frame_Add<uint8_t>(&optDataPtr, solarCellBVoltage,
"sBV");
214 Communication_Frame_Add<uint8_t>(&optDataPtr, solarCellCVoltage,
"sCV");
219 Communication_Frame_Add<int16_t>(&optDataPtr, batteryTemperature,
"batT");
224 Communication_Frame_Add<int16_t>(&optDataPtr, boardTemperature,
"brdT");
230 Communication_Frame_Add<int8_t>(&optDataPtr, mcuTemperature,
"mcuT");
238 uint8_t optData[] = { functionId, result };
251 size_t len =
radio.getPacketLength();
258 int16_t state =
radio.readData(frame, len);
261 if(state == ERR_NONE) {
262 FOSSASAT_DEBUG_PRINT(F(
"Frm "));
263 FOSSASAT_DEBUG_PRINTLN(len);
264 FOSSASAT_DEBUG_PRINT_BUFF(frame, len);
270 if(memcmp(frame, (uint8_t*)callsign, callsignLen - 1) == 0) {
274 FOSSASAT_DEBUG_PRINTLN(F(
"CErr"));
280 FOSSASAT_DEBUG_PRINT(F(
"RxErr "));
281 FOSSASAT_DEBUG_PRINT(state);
304 int16_t functionId = FCP_Get_FunctionID(callsign, frame, len);
306 FOSSASAT_DEBUG_PRINT(F(
"IdErr"));
307 FOSSASAT_DEBUG_PRINTLN(functionId);
312 FOSSASAT_DEBUG_PRINT(F(
"FID="));
313 FOSSASAT_DEBUG_PRINTLN(functionId, HEX);
316 int16_t optDataLen = 0;
318 if((functionId >= PRIVATE_OFFSET) && (functionId <= (PRIVATE_OFFSET + NUM_PRIVATE_COMMANDS))) {
324 FOSSASAT_DEBUG_PRINT(F(
"DcErr"));
325 FOSSASAT_DEBUG_PRINTLN(optDataLen);
338 }
else if(functionId < PRIVATE_OFFSET) {
342 optDataLen = FCP_Get_OptData_Length(callsign, frame, len);
345 FOSSASAT_DEBUG_PRINT(F(
"LenErr"));
346 FOSSASAT_DEBUG_PRINTLN(optDataLen);
356 FCP_Get_OptData(callsign, frame, len, optData);
360 FOSSASAT_DEBUG_PRINT(F(
"UID"));
361 FOSSASAT_DEBUG_PRINTLN(functionId, HEX);
370 FOSSASAT_DEBUG_PRINT(F(
"optLen="));
371 FOSSASAT_DEBUG_PRINTLN(optDataLen);
372 FOSSASAT_DEBUG_PRINT_BUFF(optData, (uint8_t)optDataLen);
399 case CMD_RETRANSMIT: {
407 case CMD_RETRANSMIT_CUSTOM: {
414 if(state != ERR_NONE) {
415 FOSSASAT_DEBUG_PRINT(F(
"CfgErr"));
416 FOSSASAT_DEBUG_PRINTLN(state);
424 case CMD_TRANSMIT_SYSTEM_INFO:
429 case CMD_GET_PACKET_INFO: {
431 static const uint8_t respOptDataLen = 2*
sizeof(uint8_t) + 4*
sizeof(uint16_t);
432 uint8_t respOptData[respOptDataLen];
433 uint8_t* respOptDataPtr = respOptData;
436 int8_t snr = (int8_t)(
radio.getSNR() * 4.0);
440 uint8_t rssi = (uint8_t)(
radio.getRSSI() * -2.0);
458 case CMD_GET_STATISTICS: {
462 uint8_t respOptData[34];
463 uint8_t respOptDataLen = 1;
464 uint8_t* respOptDataPtr = respOptData;
467 uint8_t flags = optData[0];
468 memcpy(respOptDataPtr, &flags,
sizeof(uint8_t));
469 respOptDataPtr +=
sizeof(uint8_t);
556 case CMD_WIPE_EEPROM:
561 case CMD_SET_TRANSMIT_ENABLE: {
575 case CMD_SET_CALLSIGN: {
580 memcpy(newCallsign, optData, optDataLen);
581 newCallsign[optDataLen] =
'\0';
585 FOSSASAT_DEBUG_PRINTLN(newCallsign);
589 case CMD_SET_SF_MODE: {
598 case CMD_SET_MPPT_MODE: {
605 powerConfig.bits.mpptTempSwitchEnabled = optData[0];
606 powerConfig.bits.mpptKeepAliveEnabled = optData[1];
613 case CMD_SET_LOW_POWER_ENABLE: {
627 case CMD_SET_RECEIVE_WINDOWS: {
637 if((Persistent_Storage_Read<uint8_t>(EEPROM_LORA_RECEIVE_LEN_ADDR) == 0) && (Persistent_Storage_Read<uint8_t>(EEPROM_FSK_RECEIVE_LEN_ADDR) == 0)) {
638 FOSSASAT_DEBUG_PRINT(F(
"Res FSK"));
644 case CMD_RECORD_SOLAR_CELLS: {
647 uint16_t numSamples = optData[0];
650 if(numSamples > 40) {
651 FOSSASAT_DEBUG_PRINT(F(
">40"));
657 memcpy(&period, optData + 1, 2);
658 FOSSASAT_DEBUG_PRINT(F(
"Rec"));
661 uint8_t respoOptDataLen = 3 * numSamples;
663 for(uint16_t i = 0; i < 3 * numSamples; i += 3) {
665 #ifdef ENABLE_INTERVAL_CONTROL 705 uint8_t len = FCP_Get_Frame_Length(callsign, optDataLen);
707 FCP_Encode(frame, callsign, respId, optDataLen, optData);
710 FOSSASAT_DEBUG_DELAY(100);
725 #ifdef ENABLE_TRANSMISSION_CONTROL 728 FOSSASAT_DEBUG_PRINTLN(F(
"Tx 0 cmd"));
729 return(ERR_TX_TIMEOUT);
734 radio.clearDio1Action();
737 FOSSASAT_DEBUG_PRINT(F(
"Send "));
738 FOSSASAT_DEBUG_PRINTLN(len);
739 FOSSASAT_DEBUG_PRINT_BUFF(data, len);
743 FOSSASAT_DEBUG_PRINT(F(
"Use "));
745 FOSSASAT_DEBUG_WRITE(MODEM_LORA);
746 FOSSASAT_DEBUG_PRINTLN(F(
" (ovr)"));
749 FOSSASAT_DEBUG_WRITE(modem);
750 FOSSASAT_DEBUG_PRINTLN();
754 uint32_t timeout = 0;
756 timeout = (float)
radio.getTimeOnAir(len) * 5.0;
758 timeout = (float)
radio.getTimeOnAir(len) * 1.5;
760 FOSSASAT_DEBUG_PRINT(F(
"T/O="));
761 FOSSASAT_DEBUG_PRINTLN(timeout);
764 int16_t state =
radio.startTransmit(data, len);
765 if(state != ERR_NONE) {
766 FOSSASAT_DEBUG_PRINT(F(
"TxErr"));
767 FOSSASAT_DEBUG_PRINTLN(state);
772 uint32_t start = micros();
773 uint32_t lastBeat = 0;
780 #ifdef ENABLE_INTERVAL_CONTROL 783 FOSSASAT_DEBUG_PRINTLN(F(
"Tx 0 bat"));
785 return(ERR_INVALID_DATA_RATE);
793 if(micros() - start > timeout) {
797 FOSSASAT_DEBUG_PRINTLN(F(
"Tx t/o"));
798 return(ERR_TX_TIMEOUT);
803 state =
radio.standby();
817 if(expected != actual) {
#define FSK_CARRIER_FREQUENCY
void System_Info_Get_Callsign(char *buff, uint8_t len)
Gets the callsign which is current set in EEPROM.
This system is the main interface that is used to transmit message, configure the radio and process r...
#define EEPROM_LORA_INVALID_COUNTER_ADDR
Start AddressEnd Address 0x000E0x000F
bool Communication_Check_OptDataLen(uint8_t expected, uint8_t actual)
Helper functions to check two variables are equal, with debug prints.
#define LORA_CURRENT_LIMIT
void Power_Control_Delay(uint32_t ms, bool sleep, bool sleepRadio=false)
This function delays the program execution for the given number of milliseconds, while maintaining th...
#define EEPROM_FSK_RECEIVE_LEN_ADDR
Start AddressEnd Address 0x00050x0005
#define EEPROM_MCU_TEMP_STATS_ADDR
Start AddressEnd Address 0x00610x0063
void Communication_Send_System_Info()
Send the satellite's information via the configured radio settings.
#define BOARD_TEMP_SENSOR_ADDR
#define EEPROM_FSK_VALID_COUNTER_ADDR
Start AddressEnd Address 0x00100x0011
#define EEPROM_LORA_RECEIVE_LEN_ADDR
Start AddressEnd Address 0x00060x0006
#define WHITENING_INITIAL
#define EEPROM_UPTIME_COUNTER_ADDR
Start AddressEnd Address 0x00070x000A
#define EEPROM_CALLSIGN_LEN_ADDR
Start AddressEnd Address 0x000140x00014
uint8_t spreadingFactorMode
void Deployment_Deploy()
This function deploys the antenna by powering the MOSFET1/2 for 1200 seconds.
bool Power_Control_Check_Battery_Limit()
Checks whether battery voltage is below low power limit. Will enable low power mode if that is the ca...
#define EEPROM_CHARGING_VOLTAGE_STATS_ADDR
Start AddressEnd Address 0x00400x0042
#define SLEEP_LENGTH_CONSTANT
void Pin_Interface_Watchdog_Heartbeat(bool manageBattery=false)
This function toggles the signal to the watchdog and writes it to the pin.
#define FSK_FREQUENCY_DEVIATION
#define EEPROM_CELL_B_VOLTAGE_STATS_ADDR
Start AddressEnd Address 0x004F0x0051
#define EEPROM_CELL_A_VOLTAGE_STATS_ADDR
Start AddressEnd Address 0x004C0x004E
float Power_Control_Get_Charging_Current()
Gets the amperage which is being provided to the battery.
float Pin_Interface_Read_Temperature(uint8_t sensorAddr)
This function reads the TMP100's value from its wire address.
#define MAX_RADIO_BUFFER_LENGTH
void Communication_Acknowledge(uint8_t functionId, uint8_t result)
This function sends acknowledge for a received frame.
void Power_Control_Save_Configuration()
Saves the configuration bytes from RAM into EEPROM.
float Power_Control_Get_Battery_Voltage()
Get the battery voltage by switching the MPPT off and then on again after reading is taken...
const uint8_t encryptionKey[]
void Power_Control_Load_Configuration()
Load the configuration bytes from the EEPROM into RAM.
#define MORSE_BATTERY_STEP
#define EEPROM_BOARD_TEMP_STATS_ADDR
Start AddressEnd Address 0x005B0x0060
volatile bool interruptsEnabled
int16_t Communication_Set_Modem(uint8_t modem)
This function configures the radio to the given modem.
#define LORA_CARRIER_FREQUENCY
int16_t Communication_Set_Configuration(uint8_t *optData, uint8_t optDataLen)
This function sets the configuration of the radio, which is used to Radio.Begin().
int16_t Communication_Transmit(uint8_t *data, uint8_t len, bool overrideModem=true)
Transmits the given data.
#define LORA_PREAMBLE_LENGTH
void Communication_Receive_Interrupt()
This function is called by the ISR when a transmission is received.
float Pin_Interface_Read_Voltage(uint8_t pin)
Read the voltage of a given pin.
#define EEPROM_BATTERY_TEMP_STATS_ADDR
Start AddressEnd Address 0x00550x005A
#define ANALOG_IN_SOLAR_C_VOLTAGE_PIN
powerConfig_t powerConfig
The current power configuration settings.
#define EEPROM_FSK_INVALID_COUNTER_ADDR
Start AddressEnd Address 0x00120x0013
void Communication_Execute_Function(uint8_t functionId, uint8_t *optData=NULL, size_t optDataLen=0)
This function executes the given function id provided with the given data.
void Communication_CW_Beep(uint32_t len)
This function transmits a continous wave "BEEP"".
void Comunication_Parse_Frame(uint8_t *frame, size_t len)
This function parses the internal contents of the message using the FOSSA COMMS Protocol.
int16_t Communication_Send_Response(uint8_t respId, uint8_t *optData=nullptr, size_t optDataLen=0, bool overrideModem=false)
Responds to a given function id execution (internally used).
void Pin_Interface_Watchdog_Restart()
Restarts the watchdog.
void Communication_Send_Morse_Beacon(float battVoltage)
This function transmits a morse beacon message.
#define FSK_CURRENT_LIMIT
float Power_Control_Get_Charging_Voltage()
Gets the charging voltage (from the solar panels) by not switching the MPPT off and taking an INA226 ...
void Communication_Process_Packet()
This function reads the contents of the radio when it receives a transmission.
#define EEPROM_CELL_C_VOLTAGE_STATS_ADDR
Start AddressEnd Address 0x00520x0054
#define WATCHDOG_LOOP_HEARTBEAT_PERIOD
void Communication_Frame_Add(uint8_t **buffPtr, T val, const char *name)
This function adds frame entry to a frame.
#define EEPROM_LORA_VALID_COUNTER_ADDR
Start AddressEnd Address 0x000C0x000D
#define FSK_PREAMBLE_LENGTH
void Persistent_Storage_Wipe()
This functions clears the EEPROM by writing EEPROM_RESET_VALUE to each memory addres.
#define MAX_STRING_LENGTH
#define EEPROM_DEPLOYMENT_COUNTER_ADDR
Start AddressEnd Address 0x00000x0000
#define MORSE_BATTERY_MIN
void System_Info_Set_Callsign(char *newCallsign)
Set the callsign to be used for each transmission to EEPROM.
#define BATTERY_TEMP_SENSOR_ADDR
#define ANALOG_IN_SOLAR_B_VOLTAGE_PIN
#define FSK_RECEIVE_WINDOW_LENGTH
int16_t Communication_Set_SpreadingFactor(uint8_t sfMode)
This function sets the spreading factor of the radio.
volatile bool dataReceived
void Persistent_Storage_Increment_Frame_Counter(bool valid)
This functions increments one of frame counters of the currently active modem in EEPROM.
int8_t Pin_Interface_Read_Temperature_Internal()
This function reads the MCU's internal temperature.
#define MAX_OPT_DATA_LENGTH
#define EEPROM_CHARGING_CURRENT_STATS_ADDR
Start AddressEnd Address 0x00430x0048
#define EEPROM_BATTERY_VOLTAGE_STATS_ADDR
Start AddressEnd Address 0x00490x004B
#define ANALOG_IN_SOLAR_A_VOLTAGE_PIN
#define EEPROM_RESTART_COUNTER_ADDR
Start AddressEnd Address 0x00030x0004
#define MORSE_PREAMBLE_LENGTH
#define LORA_OUTPUT_POWER