diff options
| author | dmlunar <root@lunar.sh> | 2025-01-22 16:47:21 +0200 |
|---|---|---|
| committer | dmlunar <root@lunar.sh> | 2025-10-15 23:42:50 +0200 |
| commit | 729f2a2c3ebfb2612d873caf453a1d7ca02180d9 (patch) | |
| tree | 7bab2fcc0c7f50eab3013348697bc06ddd71d551 /firmware | |
| download | varpa-729f2a2c3ebfb2612d873caf453a1d7ca02180d9.tar.gz varpa-729f2a2c3ebfb2612d873caf453a1d7ca02180d9.zip | |
varpa: initial public commit
Diffstat (limited to 'firmware')
36 files changed, 3524 insertions, 0 deletions
diff --git a/firmware/Makefile b/firmware/Makefile new file mode 100644 index 0000000..6045e7e --- /dev/null +++ b/firmware/Makefile @@ -0,0 +1,58 @@ +all: compile
+
+SHELL := /bin/bash
+
+MCU = atmega328p
+PROG = USBasp
+AVRDUDE = avrdude.exe
+
+LFUSE = 0xFF
+HFUSE = 0xD9
+EFUSE = 0xFF
+LOCK = 0xFF
+
+SCRIPTS_DIR = ../scripts
+SCRIPT_RESET = reset.py
+
+SRC_DIR = src
+INC_DIR = inc
+
+PYTHON = python.exe
+CC = avr-gcc
+CFLAGS = -mmcu=$(MCU) -Wall -Os -I$(INC_DIR)
+OBJ_C = avr-objcopy
+AVR_SIZE = avr-size
+
+SRC_FILES += $(SRC_DIR)/*.c
+SRC_FILES += $(SRC_DIR)/peripheral/*.c
+SRC_FILES += $(SRC_DIR)/module/*.c
+SRC_FILES += $(SRC_DIR)/driver/*.c
+
+BUILD_DIR = bin
+OUTPUT = $(BUILD_DIR)/FW_DEBUG_V_1_0
+
+reset:
+ $(PYTHON) $(SCRIPTS_DIR)/$(SCRIPT_RESET)
+
+build:
+ mkdir $(BUILD_DIR)
+ $(CC) $(CFLAGS) -o $(OUTPUT).lffw $(SRC_FILES)
+ $(AVR_SIZE) -C -x $(OUTPUT).lffw
+ $(OBJ_C) -j .text -j .data -O ihex $(OUTPUT).lffw $(OUTPUT).hex
+
+flash:
+ @read -p "ENTER TO BEGIN FLASH..."
+ $(AVRDUDE) -p $(MCU) -c $(PROG) -v -V -u -U flash:w:$(OUTPUT).hex
+
+fuze:
+ $(AVRDUDE) -p $(MCU) -c $(PROG) -v -V -u -U lfuse:w:$(LFUSE):m -U hfuse:w:$(HFUSE):m -U efuse:w:$(EFUSE):m -U lock:w:$(LOCK):m
+
+clean:
+ rm -fr $(BUILD_DIR)
+
+upload: reset clean build flash
+force-upload: clean build flash
+
+deps:
+ sudo apt install gcc-avr binutils-avr gdb-avr avr-libc avrdude make git
+
diff --git a/firmware/README.txt b/firmware/README.txt new file mode 100644 index 0000000..f90b1f0 --- /dev/null +++ b/firmware/README.txt @@ -0,0 +1,53 @@ +Dependencies +------------ + +gcc-avr binutils-avr gdb-avr avr-libc avrdude make git + +To install all dependencies, run: +make deps + +Fuse Settings +------------- + +Fuse settings are defined in the Makefile as follows: + +LFUSE = 0xFF +HFUSE = 0xD9 +EFUSE = 0xFF +LOCK = 0xFF + +System Reset +------------ + +To exclusively execute a soft reset, run: +make reset + +Firmware Compilation +-------------------- + +To exclusively build the firmware, run: +make build + +Firmware Flash +-------------- + +To exclusively execute a firmware flash, run: +make flash + +Usage +----- + +Only two commands are required to build and flash +the firmware onto the ATmega328P. + +Simply run: +make + +Then run: +make upload + +Note: + +If you encounter issues performing a soft reset, use: +make force-upload + diff --git a/firmware/inc/bsp.h b/firmware/inc/bsp.h new file mode 100644 index 0000000..2f38cfb --- /dev/null +++ b/firmware/inc/bsp.h @@ -0,0 +1,18 @@ +/** + * + * Author: Dylan Muller + * Copyright (c) 2025 + * All rights reserved. + * + * - Commercial/IP use prohibited. + * - Attribution required. + * See License.txt + * + */ + +#ifndef BSP_H_ +#define BSP_H + +void bsp_soft_reset(void); + +#endif diff --git a/firmware/inc/cmd.h b/firmware/inc/cmd.h new file mode 100644 index 0000000..11d25e0 --- /dev/null +++ b/firmware/inc/cmd.h @@ -0,0 +1,74 @@ +/** + * + * Author: Dylan Muller + * Copyright (c) 2025 + * All rights reserved. + * + * - Commercial/IP use prohibited. + * - Attribution required. + * See License.txt + * + */ + +#ifndef CMD_H_ +#define CMD_H_ + +#include <avr/pgmspace.h> + +#define CMD_MAX_ARGS 5 +#define CMD_NEWLINE "\n" + +#define CMD_DEF_ARG(x) x +#define CMD_DEF_SINGLE(x) x CMD_NEWLINE + +#define CMD_ERROR(x) printf("ERROR %s\n", x) +#define CMD_PRINT(x) printf("INFO %s\n", x) +#define CMD_PRINT_FMT(x, y) printf("INFO " x CMD_NEWLINE, y) +#define CMD_SWITCH(x, y) !strcmp(x, y) + +#define CMD_POWER_GET_STR "POWER?" +#define CMD_POWER_GET_DESC "QUERY RF POWER" + +#define CMD_POWER_SET_STR "POWER" +#define CMD_POWER_SET_DESC "SET RF POWER" + +#define CMD_TX_STR "TX" +#define CMD_TX_DESC "SWITCH TO TX MODE" + +#define CMD_RX_STR "RX" +#define CMD_RX_DESC "SWITCH TO RX MODE" + +#define CMD_DRAIN_SET_STR "DRAIN" +#define CMD_DRAIN_SET_DESC "SET DRAIN COUNTER" + +#define CMD_PROBE_STR "PROBE" +#define CMD_PROBE_DESC "START GATE PROBE" + +#define CMD_RESET_STR "RESET" +#define CMD_RESET_DESC "EXECUTE SOFT RESET" + +#define CMD_REPORT_STR "REPORT" +#define CMD_REPORT_DESC "DUMP SYSTEM REPORT" + +#define CMD_HELP_STR "HELP" +#define CMD_HELP_DESC "DUMP COMMAND LIST" + +#define CMD_LINK_REPLY_STR "REPLY" + +#define CMD_SIZE 9 +#define CMD_ENTRY_SIZE 2 + +#define CMD_POWER_GET CMD_DEF_SINGLE(CMD_POWER_GET_STR) +#define CMD_POWER_SET CMD_DEF_ARG(CMD_POWER_SET_STR) +#define CMD_TX CMD_DEF_SINGLE(CMD_TX_STR) +#define CMD_RX CMD_DEF_SINGLE(CMD_RX_STR) +#define CMD_DRAIN_SET CMD_DEF_ARG(CMD_DRAIN_SET_STR) +#define CMD_PROBE CMD_DEF_SINGLE(CMD_PROBE_STR) +#define CMD_RESET CMD_DEF_SINGLE(CMD_RESET_STR) +#define CMD_REPORT CMD_DEF_SINGLE(CMD_REPORT_STR) +#define CMD_HELP CMD_DEF_SINGLE(CMD_HELP_STR) +#define CMD_LINK_REPLY CMD_DEF_SINGLE(CMD_LINK_REPLY_STR) + +extern const char* const cmd_lut[][2]; + +#endif diff --git a/firmware/inc/driver/device.h b/firmware/inc/driver/device.h new file mode 100644 index 0000000..b8528c2 --- /dev/null +++ b/firmware/inc/driver/device.h @@ -0,0 +1,25 @@ +/** + * + * Author: Dylan Muller + * Copyright (c) 2025 + * All rights reserved. + * + * - Commercial/IP use prohibited. + * - Attribution required. + * See License.txt + * + */ + +#ifndef DEVICE_H_ +#define DEVICE_H_ + +#include <stdint.h> + +typedef struct +{ + uint8_t dev_id; + uint8_t dev_ss; + uint8_t* dev_port; +} t_dev; + +#endif diff --git a/firmware/inc/driver/f1956.h b/firmware/inc/driver/f1956.h new file mode 100644 index 0000000..79c5f0b --- /dev/null +++ b/firmware/inc/driver/f1956.h @@ -0,0 +1,41 @@ +/** + * + * Author: Dylan Muller + * Copyright (c) 2025 + * All rights reserved. + * + * - Commercial/IP use prohibited. + * - Attribution required. + * See License.txt + * + */ + +#ifndef F1956_H_ +#define F1956_H_ + +#include "setup.h" + +#include <stdint.h> +#include <avr/io.h> + +#define F1956_ID_INPUT_ATT 0xC1 + +#define F1956_DEV_0 0 +#define F1956_DEV_INPUT_ATT F1956_DEV_0 + +#define F1956_DEV_INPUT_ATT_ADDR 0x0 + +#define F1956_DEV_0_PORT PORTC +#define F1956_DEV_0_DDR DDRC +#define F1956_DEV_0_SS PORTC2 + +void att_init( + uint8_t init_value +); + +void att_set( + uint8_t id, + uint8_t value +); + +#endif diff --git a/firmware/inc/driver/mcp3202.h b/firmware/inc/driver/mcp3202.h new file mode 100644 index 0000000..b995834 --- /dev/null +++ b/firmware/inc/driver/mcp3202.h @@ -0,0 +1,82 @@ +/** + * + * Author: Dylan Muller + * Copyright (c) 2025 + * All rights reserved. + * + * - Commercial/IP use prohibited. + * - Attribution required. + * See License.txt + * + */ + +#ifndef MCP3202_H_ +#define MCP3202_H_ + +#include <stdint.h> +#include <avr/io.h> + +#define MCP3202_BIT_MSBBF(x) (x << 5) +#define MCP3202_BIT_ODD(x) (x << 6) +#define MCP3202_BIT_SGL(x) (x << 7) +#define MCP3202_BIT_START (1 << 0) + +#define MCP3202_DAQ_MSB 0x2 +#define MCP3202_DAQ_LSB 0x1 + +#define MCP3202_BUILD_REQ(MSBF, ODD, SGL) \ + (uint8_t)(MCP3202_BIT_MSBBF(MSBF) | \ + MCP3202_BIT_ODD(ODD) | \ + MCP3202_BIT_SGL(SGL)) + +#define MCP3202_REQ_START (uint8_t)(MCP3202_BIT_START) +#define MCP3202_REQ_CH0 MCP3202_BUILD_REQ(1, 0, 1) +#define MCP3202_REQ_CH1 MCP3202_BUILD_REQ(1, 1, 1) +#define MCP3202_REQ_PAD (uint8_t)(0x0) + +#define MCP3202_ID_FW_POWER 0xA1 +#define MCP3202_ID_REV_POWER 0xA2 +#define MCP3202_ID_DRAIN_VOLT 0xA3 +#define MCP3202_ID_DRAIN_AMP 0xA4 + +#define MCP3202_CHN_0 0 +#define MCP3202_CHN_1 1 + +#define MCP3202_CHN_DRAIN_VOLT MCP3202_CHN_0 +#define MCP3202_CHN_DRAIN_AMP MCP3202_CHN_1 +#define MCP3202_CHN_FW_POWER MCP3202_CHN_1 +#define MCP3202_CHN_REV_POWER MCP3202_CHN_0 + +#define MCP3202_DEV_0 0 +#define MCP3202_DEV_1 1 + +#define MCP3202_DEV_DRAIN_VOLT MCP3202_DEV_0 +#define MCP3202_DEV_DRAIN_AMP MCP3202_DEV_0 +#define MCP3202_DEV_FW_POWER MCP3202_DEV_1 +#define MCP3202_DEV_REV_POWER MCP3202_DEV_1 + +#define MCP3202_DEV_0_PORT PORTC +#define MCP3202_DEV_0_DDR DDRC +#define MCP3202_DEV_0_SS PORTC0 +#define MCP3202_DEV_1_PORT PORTC +#define MCP3202_DEV_1_DDR DDRC +#define MCP3202_DEV_1_SS PORTC1 + +#define MCP3202_DRAIN_VOLT_GAIN 26 +#define MCP3202_DRAIN_AMP_GAIN 25 + + +void adc_init(void); + +uint16_t adc_read( + uint8_t id, + uint8_t conv_bypass +); + +uint16_t adc_read_n( + uint8_t id, + uint8_t n +); + + +#endif diff --git a/firmware/inc/driver/mcp4725.h b/firmware/inc/driver/mcp4725.h new file mode 100644 index 0000000..06f6281 --- /dev/null +++ b/firmware/inc/driver/mcp4725.h @@ -0,0 +1,48 @@ +/** + * + * Author: Dylan Muller + * Copyright (c) 2025 + * All rights reserved. + * + * - Commercial/IP use prohibited. + * - Attribution required. + * See License.txt + * + */ + +#ifndef MCP4725_H_ +#define MCP4725_H_ + +#define MCP4725_BIT_PD0(x) (x << 4) +#define MCP4725_BIT_PD1(x) (x << 5) + +#define MCP4725_ID_GATE_VOLT 0xB1 +#define MCP4725_ID_DRAIN_VOLT 0xB2 + +#define MCP4725_DEV_0 0 +#define MCP4725_DEV_1 1 + +#define MCP4725_DEV_GATE_VOLT MCP4725_DEV_0 +#define MCP4725_DEV_DRAIN_VOLT MCP4725_DEV_1 + +#define MCP4725_DEV_GATE_VOLT_ADDR 0x60 +#define MCP4725_DEV_DRAIN_VOLT_ADDR 0x61 + +#define MCP4725_DRAIN_GAIN 23 + +void dac_init( + uint16_t init_value +); + +void dac_write( + uint8_t id, + uint16_t value, + uint8_t conv_bypass +); + +uint16_t dac_read( + uint8_t id, + uint8_t conv_bypass +); + +#endif diff --git a/firmware/inc/driver/radio_config.h b/firmware/inc/driver/radio_config.h new file mode 100644 index 0000000..ff079a7 --- /dev/null +++ b/firmware/inc/driver/radio_config.h @@ -0,0 +1,680 @@ +/*! @file radio_config.h + * @brief This file contains the automatically generated + * configurations. + * + * @n WDS GUI Version: 3.2.11.0 + * @n Device: Si4468 Rev.: A2 + * + * @b COPYRIGHT + * @n Silicon Laboratories Confidential + * @n Copyright 2017 Silicon Laboratories, Inc. + * @n http://www.silabs.com + */ + +#ifndef RADIO_CONFIG_H_ +#define RADIO_CONFIG_H_ + +// USER DEFINED PARAMETERS +// Define your own parameters here + +// INPUT DATA +/* +// Crys_freq(Hz): 30000000 Crys_tol(ppm): 20 IF_mode: 2 High_perf_Ch_Fil: 1 OSRtune: 0 Ch_Fil_Bw_AFC: 0 ANT_DIV: 0 PM_pattern: 0 +// MOD_type: 2 Rsymb(sps): 1000 Fdev(Hz): 2000 RXBW(Hz): 150000 Manchester: 0 AFC_en: 0 Rsymb_error: 0.0 Chip-Version: 2 +// RF Freq.(MHz): 169.4 API_TC: 29 fhst: 250000 inputBW: 0 BERT: 0 RAW_dout: 0 D_source: 0 Hi_pfm_div: 1 +// API_ARR_Det_en: 0 Fdev_error: 0 API_ETSI: 0 +// +// # RX IF frequency is -468750 Hz +// # WB filter 1 (BW = 19.08 kHz); NB-filter 1 (BW = 19.08 kHz) +// +// Modulation index: 4 +*/ + + +// CONFIGURATION PARAMETERS +#define RADIO_CONFIGURATION_DATA_RADIO_XO_FREQ 30000000L +#define RADIO_CONFIGURATION_DATA_CHANNEL_NUMBER 0x00 +#define RADIO_CONFIGURATION_DATA_RADIO_PACKET_LENGTH 0x07 +#define RADIO_CONFIGURATION_DATA_RADIO_STATE_AFTER_POWER_UP 0x03 +#define RADIO_CONFIGURATION_DATA_RADIO_DELAY_CNT_AFTER_RESET 0xF000 + + +// CONFIGURATION COMMANDS + +/* +// Command: RF_POWER_UP +// Description: Command to power-up the device and select the operational mode and functionality. +*/ +#define RF_POWER_UP 0x02, 0x01, 0x00, 0x01, 0xC9, 0xC3, 0x80 + +/* +// Command: RF_GPIO_PIN_CFG +// Description: Configures the GPIO pins. +*/ +#define RF_GPIO_PIN_CFG 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + +/* +// Set properties: RF_GLOBAL_XO_TUNE_2 +// Number of properties: 2 +// Group ID: 0x00 +// Start ID: 0x00 +// Default values: 0x40, 0x00, +// Descriptions: +// GLOBAL_XO_TUNE - Configure the internal capacitor frequency tuning bank for the crystal oscillator. +// GLOBAL_CLK_CFG - Clock configuration options. +*/ +#define RF_GLOBAL_XO_TUNE_2 0x11, 0x00, 0x02, 0x00, 0x52, 0x00 + +/* +// Set properties: RF_GLOBAL_CONFIG_1 +// Number of properties: 1 +// Group ID: 0x00 +// Start ID: 0x03 +// Default values: 0x20, +// Descriptions: +// GLOBAL_CONFIG - Global configuration settings. +*/ +#define RF_GLOBAL_CONFIG_1 0x11, 0x00, 0x01, 0x03, 0x20 + +/* +// Set properties: RF_INT_CTL_ENABLE_2 +// Number of properties: 2 +// Group ID: 0x01 +// Start ID: 0x00 +// Default values: 0x04, 0x00, +// Descriptions: +// INT_CTL_ENABLE - This property provides for global enabling of the three interrupt groups (Chip, Modem and Packet Handler) in order to generate HW interrupts at the NIRQ pin. +// INT_CTL_PH_ENABLE - Enable individual interrupt sources within the Packet Handler Interrupt Group to generate a HW interrupt on the NIRQ output pin. +*/ +#define RF_INT_CTL_ENABLE_2 0x11, 0x01, 0x02, 0x00, 0x01, 0xFF + +/* +// Set properties: RF_FRR_CTL_A_MODE_4 +// Number of properties: 4 +// Group ID: 0x02 +// Start ID: 0x00 +// Default values: 0x01, 0x02, 0x09, 0x00, +// Descriptions: +// FRR_CTL_A_MODE - Fast Response Register A Configuration. +// FRR_CTL_B_MODE - Fast Response Register B Configuration. +// FRR_CTL_C_MODE - Fast Response Register C Configuration. +// FRR_CTL_D_MODE - Fast Response Register D Configuration. +*/ +#define RF_FRR_CTL_A_MODE_4 0x11, 0x02, 0x04, 0x00, 0x0A, 0x09, 0x00, 0x00 + +/* +// Set properties: RF_PREAMBLE_TX_LENGTH_9 +// Number of properties: 9 +// Group ID: 0x10 +// Start ID: 0x00 +// Default values: 0x08, 0x14, 0x00, 0x0F, 0x21, 0x00, 0x00, 0x00, 0x00, +// Descriptions: +// PREAMBLE_TX_LENGTH - Configure length of TX Preamble. +// PREAMBLE_CONFIG_STD_1 - Configuration of reception of a packet with a Standard Preamble pattern. +// PREAMBLE_CONFIG_NSTD - Configuration of transmission/reception of a packet with a Non-Standard Preamble pattern. +// PREAMBLE_CONFIG_STD_2 - Configuration of timeout periods during reception of a packet with Standard Preamble pattern. +// PREAMBLE_CONFIG - General configuration bits for the Preamble field. +// PREAMBLE_PATTERN_31_24 - Configuration of the bit values describing a Non-Standard Preamble pattern. +// PREAMBLE_PATTERN_23_16 - Configuration of the bit values describing a Non-Standard Preamble pattern. +// PREAMBLE_PATTERN_15_8 - Configuration of the bit values describing a Non-Standard Preamble pattern. +// PREAMBLE_PATTERN_7_0 - Configuration of the bit values describing a Non-Standard Preamble pattern. +*/ +#define RF_PREAMBLE_TX_LENGTH_9 0x11, 0x10, 0x09, 0x00, 0x08, 0x14, 0x00, 0x0F, 0x31, 0x00, 0x00, 0x00, 0x00 + +/* +// Set properties: RF_SYNC_CONFIG_10 +// Number of properties: 10 +// Group ID: 0x11 +// Start ID: 0x00 +// Default values: 0x01, 0x2D, 0xD4, 0x2D, 0xD4, 0x00, 0x2D, 0xD4, 0x2D, 0xD4, +// Descriptions: +// SYNC_CONFIG - Sync Word configuration bits. +// SYNC_BITS_31_24 - Sync word. +// SYNC_BITS_23_16 - Sync word. +// SYNC_BITS_15_8 - Sync word. +// SYNC_BITS_7_0 - Sync word. +// SYNC_CONFIG2 - Sync Word configuration bits. +// SYNC_BITS2_31_24 - Sync word 2. +// SYNC_BITS2_23_16 - Sync word 2. +// SYNC_BITS2_15_8 - Sync word 2. +// SYNC_BITS2_7_0 - Sync word 2. +*/ +#define RF_SYNC_CONFIG_10 0x11, 0x11, 0x0A, 0x00, 0x01, 0xB4, 0x2B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + +/* +// Set properties: RF_PKT_CRC_CONFIG_12 +// Number of properties: 12 +// Group ID: 0x12 +// Start ID: 0x00 +// Default values: 0x00, 0x01, 0x08, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, +// Descriptions: +// PKT_CRC_CONFIG - Select a CRC polynomial and seed. +// PKT_WHT_POLY_15_8 - 16-bit polynomial value for the PN Generator (e.g., for Data Whitening) +// PKT_WHT_POLY_7_0 - 16-bit polynomial value for the PN Generator (e.g., for Data Whitening) +// PKT_WHT_SEED_15_8 - 16-bit seed value for the PN Generator (e.g., for Data Whitening) +// PKT_WHT_SEED_7_0 - 16-bit seed value for the PN Generator (e.g., for Data Whitening) +// PKT_WHT_BIT_NUM - Selects which bit of the LFSR (used to generate the PN / data whitening sequence) is used as the output bit for data scrambling. +// PKT_CONFIG1 - General configuration bits for transmission or reception of a packet. +// PKT_CONFIG2 - General packet configuration bits. +// PKT_LEN - Configuration bits for reception of a variable length packet. +// PKT_LEN_FIELD_SOURCE - Field number containing the received packet length byte(s). +// PKT_LEN_ADJUST - Provides for adjustment/offset of the received packet length value (in order to accommodate a variety of methods of defining total packet length). +// PKT_TX_THRESHOLD - TX FIFO almost empty threshold. +*/ +#define RF_PKT_CRC_CONFIG_12 0x11, 0x12, 0x0C, 0x00, 0x00, 0x01, 0x08, 0xFF, 0xFF, 0x20, 0x02, 0x00, 0x00, 0x00, 0x00, 0x30 + +/* +// Set properties: RF_PKT_RX_THRESHOLD_12 +// Number of properties: 12 +// Group ID: 0x12 +// Start ID: 0x0C +// Default values: 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +// Descriptions: +// PKT_RX_THRESHOLD - RX FIFO Almost Full threshold. +// PKT_FIELD_1_LENGTH_12_8 - Unsigned 13-bit Field 1 length value. +// PKT_FIELD_1_LENGTH_7_0 - Unsigned 13-bit Field 1 length value. +// PKT_FIELD_1_CONFIG - General data processing and packet configuration bits for Field 1. +// PKT_FIELD_1_CRC_CONFIG - Configuration of CRC control bits across Field 1. +// PKT_FIELD_2_LENGTH_12_8 - Unsigned 13-bit Field 2 length value. +// PKT_FIELD_2_LENGTH_7_0 - Unsigned 13-bit Field 2 length value. +// PKT_FIELD_2_CONFIG - General data processing and packet configuration bits for Field 2. +// PKT_FIELD_2_CRC_CONFIG - Configuration of CRC control bits across Field 2. +// PKT_FIELD_3_LENGTH_12_8 - Unsigned 13-bit Field 3 length value. +// PKT_FIELD_3_LENGTH_7_0 - Unsigned 13-bit Field 3 length value. +// PKT_FIELD_3_CONFIG - General data processing and packet configuration bits for Field 3. +*/ +#define RF_PKT_RX_THRESHOLD_12 0x11, 0x12, 0x0C, 0x0C, 0x30, 0x00, 0x01, 0x04, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00 + +/* +// Set properties: RF_PKT_FIELD_3_CRC_CONFIG_12 +// Number of properties: 12 +// Group ID: 0x12 +// Start ID: 0x18 +// Default values: 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +// Descriptions: +// PKT_FIELD_3_CRC_CONFIG - Configuration of CRC control bits across Field 3. +// PKT_FIELD_4_LENGTH_12_8 - Unsigned 13-bit Field 4 length value. +// PKT_FIELD_4_LENGTH_7_0 - Unsigned 13-bit Field 4 length value. +// PKT_FIELD_4_CONFIG - General data processing and packet configuration bits for Field 4. +// PKT_FIELD_4_CRC_CONFIG - Configuration of CRC control bits across Field 4. +// PKT_FIELD_5_LENGTH_12_8 - Unsigned 13-bit Field 5 length value. +// PKT_FIELD_5_LENGTH_7_0 - Unsigned 13-bit Field 5 length value. +// PKT_FIELD_5_CONFIG - General data processing and packet configuration bits for Field 5. +// PKT_FIELD_5_CRC_CONFIG - Configuration of CRC control bits across Field 5. +// PKT_RX_FIELD_1_LENGTH_12_8 - Unsigned 13-bit RX Field 1 length value. +// PKT_RX_FIELD_1_LENGTH_7_0 - Unsigned 13-bit RX Field 1 length value. +// PKT_RX_FIELD_1_CONFIG - General data processing and packet configuration bits for RX Field 1. +*/ +#define RF_PKT_FIELD_3_CRC_CONFIG_12 0x11, 0x12, 0x0C, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + +/* +// Set properties: RF_PKT_RX_FIELD_1_CRC_CONFIG_12 +// Number of properties: 12 +// Group ID: 0x12 +// Start ID: 0x24 +// Default values: 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +// Descriptions: +// PKT_RX_FIELD_1_CRC_CONFIG - Configuration of CRC control bits across RX Field 1. +// PKT_RX_FIELD_2_LENGTH_12_8 - Unsigned 13-bit RX Field 2 length value. +// PKT_RX_FIELD_2_LENGTH_7_0 - Unsigned 13-bit RX Field 2 length value. +// PKT_RX_FIELD_2_CONFIG - General data processing and packet configuration bits for RX Field 2. +// PKT_RX_FIELD_2_CRC_CONFIG - Configuration of CRC control bits across RX Field 2. +// PKT_RX_FIELD_3_LENGTH_12_8 - Unsigned 13-bit RX Field 3 length value. +// PKT_RX_FIELD_3_LENGTH_7_0 - Unsigned 13-bit RX Field 3 length value. +// PKT_RX_FIELD_3_CONFIG - General data processing and packet configuration bits for RX Field 3. +// PKT_RX_FIELD_3_CRC_CONFIG - Configuration of CRC control bits across RX Field 3. +// PKT_RX_FIELD_4_LENGTH_12_8 - Unsigned 13-bit RX Field 4 length value. +// PKT_RX_FIELD_4_LENGTH_7_0 - Unsigned 13-bit RX Field 4 length value. +// PKT_RX_FIELD_4_CONFIG - General data processing and packet configuration bits for RX Field 4. +*/ +#define RF_PKT_RX_FIELD_1_CRC_CONFIG_12 0x11, 0x12, 0x0C, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + +/* +// Set properties: RF_PKT_RX_FIELD_4_CRC_CONFIG_5 +// Number of properties: 5 +// Group ID: 0x12 +// Start ID: 0x30 +// Default values: 0x00, 0x00, 0x00, 0x00, 0x00, +// Descriptions: +// PKT_RX_FIELD_4_CRC_CONFIG - Configuration of CRC control bits across RX Field 4. +// PKT_RX_FIELD_5_LENGTH_12_8 - Unsigned 13-bit RX Field 5 length value. +// PKT_RX_FIELD_5_LENGTH_7_0 - Unsigned 13-bit RX Field 5 length value. +// PKT_RX_FIELD_5_CONFIG - General data processing and packet configuration bits for RX Field 5. +// PKT_RX_FIELD_5_CRC_CONFIG - Configuration of CRC control bits across RX Field 5. +*/ +#define RF_PKT_RX_FIELD_4_CRC_CONFIG_5 0x11, 0x12, 0x05, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00 + +/* +// Set properties: RF_PKT_CRC_SEED_31_24_4 +// Number of properties: 4 +// Group ID: 0x12 +// Start ID: 0x36 +// Default values: 0x00, 0x00, 0x00, 0x00, +// Descriptions: +// PKT_CRC_SEED_31_24 - 32-bit seed value for the 32-bit CRC engine +// PKT_CRC_SEED_23_16 - 32-bit seed value for the 32-bit CRC engine +// PKT_CRC_SEED_15_8 - 32-bit seed value for the 32-bit CRC engine +// PKT_CRC_SEED_7_0 - 32-bit seed value for the 32-bit CRC engine +*/ +#define RF_PKT_CRC_SEED_31_24_4 0x11, 0x12, 0x04, 0x36, 0x00, 0x00, 0x00, 0x00 + +/* +// Set properties: RF_MODEM_MOD_TYPE_12 +// Number of properties: 12 +// Group ID: 0x20 +// Start ID: 0x00 +// Default values: 0x02, 0x80, 0x07, 0x0F, 0x42, 0x40, 0x01, 0xC9, 0xC3, 0x80, 0x00, 0x06, +// Descriptions: +// MODEM_MOD_TYPE - Selects the type of modulation. In TX mode, additionally selects the source of the modulation. +// MODEM_MAP_CONTROL - Controls polarity and mapping of transmit and receive bits. +// MODEM_DSM_CTRL - Miscellaneous control bits for the Delta-Sigma Modulator (DSM) in the PLL Synthesizer. +// MODEM_DATA_RATE_2 - Unsigned 24-bit value used to determine the TX data rate +// MODEM_DATA_RATE_1 - Unsigned 24-bit value used to determine the TX data rate +// MODEM_DATA_RATE_0 - Unsigned 24-bit value used to determine the TX data rate +// MODEM_TX_NCO_MODE_3 - TX Gaussian filter oversampling ratio and Byte 3 of unsigned 26-bit TX Numerically Controlled Oscillator (NCO) modulus. +// MODEM_TX_NCO_MODE_2 - TX Gaussian filter oversampling ratio and Byte 3 of unsigned 26-bit TX Numerically Controlled Oscillator (NCO) modulus. +// MODEM_TX_NCO_MODE_1 - TX Gaussian filter oversampling ratio and Byte 3 of unsigned 26-bit TX Numerically Controlled Oscillator (NCO) modulus. +// MODEM_TX_NCO_MODE_0 - TX Gaussian filter oversampling ratio and Byte 3 of unsigned 26-bit TX Numerically Controlled Oscillator (NCO) modulus. +// MODEM_FREQ_DEV_2 - 17-bit unsigned TX frequency deviation word. +// MODEM_FREQ_DEV_1 - 17-bit unsigned TX frequency deviation word. +*/ +#define RF_MODEM_MOD_TYPE_12 0x11, 0x20, 0x0C, 0x00, 0x00, 0x00, 0x07, 0x00, 0x27, 0x10, 0x01, 0xC9, 0xC3, 0x80, 0x00, 0x01 + +/* +// Set properties: RF_MODEM_FREQ_DEV_0_1 +// Number of properties: 1 +// Group ID: 0x20 +// Start ID: 0x0C +// Default values: 0xD3, +// Descriptions: +// MODEM_FREQ_DEV_0 - 17-bit unsigned TX frequency deviation word. +*/ +#define RF_MODEM_FREQ_DEV_0_1 0x11, 0x20, 0x01, 0x0C, 0xA3 + +/* +// Set properties: RF_MODEM_TX_RAMP_DELAY_12 +// Number of properties: 12 +// Group ID: 0x20 +// Start ID: 0x18 +// Default values: 0x01, 0x00, 0x08, 0x03, 0xC0, 0x00, 0x10, 0x20, 0x00, 0x00, 0x00, 0x4B, +// Descriptions: +// MODEM_TX_RAMP_DELAY - TX ramp-down delay setting. +// MODEM_MDM_CTRL - MDM control. +// MODEM_IF_CONTROL - Selects Fixed-IF, Scaled-IF, or Zero-IF mode of RX Modem operation. +// MODEM_IF_FREQ_2 - the IF frequency setting (an 18-bit signed number). +// MODEM_IF_FREQ_1 - the IF frequency setting (an 18-bit signed number). +// MODEM_IF_FREQ_0 - the IF frequency setting (an 18-bit signed number). +// MODEM_DECIMATION_CFG1 - Specifies three decimator ratios for the Cascaded Integrator Comb (CIC) filter. +// MODEM_DECIMATION_CFG0 - Specifies miscellaneous parameters and decimator ratios for the Cascaded Integrator Comb (CIC) filter. +// MODEM_DECIMATION_CFG2 - Specifies miscellaneous decimator filter selections. +// MODEM_IFPKD_THRESHOLDS - +// MODEM_BCR_OSR_1 - RX BCR/Slicer oversampling rate (12-bit unsigned number). +// MODEM_BCR_OSR_0 - RX BCR/Slicer oversampling rate (12-bit unsigned number). +*/ +#define RF_MODEM_TX_RAMP_DELAY_12 0x11, 0x20, 0x0C, 0x18, 0x01, 0x80, 0x08, 0x02, 0x80, 0x00, 0x70, 0x10, 0x14, 0xE8, 0x02, 0x71 + +/* +// Set properties: RF_MODEM_BCR_NCO_OFFSET_2_12 +// Number of properties: 12 +// Group ID: 0x20 +// Start ID: 0x24 +// Default values: 0x06, 0xD3, 0xA0, 0x06, 0xD3, 0x02, 0xC0, 0x00, 0x00, 0x23, 0x83, 0x69, +// Descriptions: +// MODEM_BCR_NCO_OFFSET_2 - RX BCR NCO offset value (an unsigned 22-bit number). +// MODEM_BCR_NCO_OFFSET_1 - RX BCR NCO offset value (an unsigned 22-bit number). +// MODEM_BCR_NCO_OFFSET_0 - RX BCR NCO offset value (an unsigned 22-bit number). +// MODEM_BCR_GAIN_1 - The unsigned 11-bit RX BCR loop gain value. +// MODEM_BCR_GAIN_0 - The unsigned 11-bit RX BCR loop gain value. +// MODEM_BCR_GEAR - RX BCR loop gear control. +// MODEM_BCR_MISC1 - Miscellaneous control bits for the RX BCR loop. +// MODEM_BCR_MISC0 - Miscellaneous RX BCR loop controls. +// MODEM_AFC_GEAR - RX AFC loop gear control. +// MODEM_AFC_WAIT - RX AFC loop wait time control. +// MODEM_AFC_GAIN_1 - Sets the gain of the PLL-based AFC acquisition loop, and provides miscellaneous control bits for AFC functionality. +// MODEM_AFC_GAIN_0 - Sets the gain of the PLL-based AFC acquisition loop, and provides miscellaneous control bits for AFC functionality. +*/ +#define RF_MODEM_BCR_NCO_OFFSET_2_12 0x11, 0x20, 0x0C, 0x24, 0x00, 0xD1, 0xB7, 0x00, 0x69, 0x02, 0xC2, 0x00, 0x04, 0x23, 0x80, 0x09 + +/* +// Set properties: RF_MODEM_AFC_LIMITER_1_3 +// Number of properties: 3 +// Group ID: 0x20 +// Start ID: 0x30 +// Default values: 0x00, 0x40, 0xA0, +// Descriptions: +// MODEM_AFC_LIMITER_1 - Set the AFC limiter value. +// MODEM_AFC_LIMITER_0 - Set the AFC limiter value. +// MODEM_AFC_MISC - Specifies miscellaneous AFC control bits. +*/ +#define RF_MODEM_AFC_LIMITER_1_3 0x11, 0x20, 0x03, 0x30, 0x24, 0x15, 0x80 + +/* +// Set properties: RF_MODEM_AGC_CONTROL_1 +// Number of properties: 1 +// Group ID: 0x20 +// Start ID: 0x35 +// Default values: 0xE0, +// Descriptions: +// MODEM_AGC_CONTROL - Miscellaneous control bits for the Automatic Gain Control (AGC) function in the RX Chain. +*/ +#define RF_MODEM_AGC_CONTROL_1 0x11, 0x20, 0x01, 0x35, 0xE0 + +/* +// Set properties: RF_MODEM_AGC_WINDOW_SIZE_12 +// Number of properties: 12 +// Group ID: 0x20 +// Start ID: 0x38 +// Default values: 0x11, 0x10, 0x10, 0x0B, 0x1C, 0x40, 0x00, 0x00, 0x2B, 0x0C, 0xA4, 0x03, +// Descriptions: +// MODEM_AGC_WINDOW_SIZE - Specifies the size of the measurement and settling windows for the AGC algorithm. +// MODEM_AGC_RFPD_DECAY - Sets the decay time of the RF peak detectors. +// MODEM_AGC_IFPD_DECAY - Sets the decay time of the IF peak detectors. +// MODEM_FSK4_GAIN1 - Specifies the gain factor of the secondary branch in 4(G)FSK ISI-suppression. +// MODEM_FSK4_GAIN0 - Specifies the gain factor of the primary branch in 4(G)FSK ISI-suppression. +// MODEM_FSK4_TH1 - 16 bit 4(G)FSK slicer threshold. +// MODEM_FSK4_TH0 - 16 bit 4(G)FSK slicer threshold. +// MODEM_FSK4_MAP - 4(G)FSK symbol mapping code. +// MODEM_OOK_PDTC - Configures the attack and decay times of the OOK Peak Detector. +// MODEM_OOK_BLOPK - Configures the slicing reference level of the OOK Peak Detector. +// MODEM_OOK_CNT1 - OOK control. +// MODEM_OOK_MISC - Selects the detector(s) used for demodulation of an OOK signal, or for demodulation of a (G)FSK signal when using the asynchronous demodulator. +*/ +#define RF_MODEM_AGC_WINDOW_SIZE_12 0x11, 0x20, 0x0C, 0x38, 0x11, 0x89, 0x89, 0x80, 0x02, 0xFF, 0xFF, 0x00, 0x2B, 0x0C, 0xA4, 0x22 + +/* +// Set properties: RF_MODEM_RAW_CONTROL_10 +// Number of properties: 10 +// Group ID: 0x20 +// Start ID: 0x45 +// Default values: 0x02, 0x00, 0xA3, 0x02, 0x80, 0xFF, 0x0C, 0x01, 0x00, 0x40, +// Descriptions: +// MODEM_RAW_CONTROL - Defines gain and enable controls for raw / nonstandard mode. +// MODEM_RAW_EYE_1 - 11 bit eye-open detector threshold. +// MODEM_RAW_EYE_0 - 11 bit eye-open detector threshold. +// MODEM_ANT_DIV_MODE - Antenna diversity mode settings. +// MODEM_ANT_DIV_CONTROL - Specifies controls for the Antenna Diversity algorithm. +// MODEM_RSSI_THRESH - Configures the RSSI threshold. +// MODEM_RSSI_JUMP_THRESH - Configures the RSSI Jump Detection threshold. +// MODEM_RSSI_CONTROL - Control of the averaging modes and latching time for reporting RSSI value(s). +// MODEM_RSSI_CONTROL2 - RSSI Jump Detection control. +// MODEM_RSSI_COMP - RSSI compensation value. +*/ +#define RF_MODEM_RAW_CONTROL_10 0x11, 0x20, 0x0A, 0x45, 0x83, 0x00, 0xCC, 0x01, 0x00, 0xFF, 0x06, 0x00, 0x18, 0x40 + +/* +// Set properties: RF_MODEM_RAW_SEARCH2_2 +// Number of properties: 2 +// Group ID: 0x20 +// Start ID: 0x50 +// Default values: 0x00, 0x08, +// Descriptions: +// MODEM_RAW_SEARCH2 - Defines and controls the search period length for the Moving Average and Min-Max detectors. +// MODEM_CLKGEN_BAND - Select PLL Synthesizer output divider ratio as a function of frequency band. +*/ +#define RF_MODEM_RAW_SEARCH2_2 0x11, 0x20, 0x02, 0x50, 0x84, 0x0D + +/* +// Set properties: RF_MODEM_SPIKE_DET_2 +// Number of properties: 2 +// Group ID: 0x20 +// Start ID: 0x54 +// Default values: 0x00, 0x00, +// Descriptions: +// MODEM_SPIKE_DET - Configures the threshold for (G)FSK Spike Detection. +// MODEM_ONE_SHOT_AFC - Configures parameters for th e One Shot AFC function and for BCR timing/acquisition. +*/ +#define RF_MODEM_SPIKE_DET_2 0x11, 0x20, 0x02, 0x54, 0x03, 0x07 + +/* +// Set properties: RF_MODEM_RSSI_MUTE_1 +// Number of properties: 1 +// Group ID: 0x20 +// Start ID: 0x57 +// Default values: 0x00, +// Descriptions: +// MODEM_RSSI_MUTE - Configures muting of the RSSI to avoid false RSSI interrupts. +*/ +#define RF_MODEM_RSSI_MUTE_1 0x11, 0x20, 0x01, 0x57, 0x00 + +/* +// Set properties: RF_MODEM_DSA_CTRL1_5 +// Number of properties: 5 +// Group ID: 0x20 +// Start ID: 0x5B +// Default values: 0x00, 0x00, 0x00, 0x00, 0x00, +// Descriptions: +// MODEM_DSA_CTRL1 - Configures parameters for the Signal Arrival Detection circuit block and algorithm. +// MODEM_DSA_CTRL2 - Configures parameters for the Signal Arrival Detection circuit block and algorithm. +// MODEM_DSA_QUAL - Configures parameters for the Eye Opening qualification m ethod of the Signal Arrival Detection algorithm. +// MODEM_DSA_RSSI - Signal Arrival Detect RSSI Qualifier Config +// MODEM_DSA_MISC - Miscellaneous detection of signal arrival bits. +*/ +#define RF_MODEM_DSA_CTRL1_5 0x11, 0x20, 0x05, 0x5B, 0x40, 0x04, 0x09, 0x78, 0x20 + +/* +// Set properties: RF_MODEM_CHFLT_RX1_CHFLT_COE13_7_0_12 +// Number of properties: 12 +// Group ID: 0x21 +// Start ID: 0x00 +// Default values: 0xFF, 0xBA, 0x0F, 0x51, 0xCF, 0xA9, 0xC9, 0xFC, 0x1B, 0x1E, 0x0F, 0x01, +// Descriptions: +// MODEM_CHFLT_RX1_CHFLT_COE13_7_0 - Filter coefficients for the first set of RX filter coefficients. +// MODEM_CHFLT_RX1_CHFLT_COE12_7_0 - Filter coefficients for the first set of RX filter coefficients. +// MODEM_CHFLT_RX1_CHFLT_COE11_7_0 - Filter coefficients for the first set of RX filter coefficients. +// MODEM_CHFLT_RX1_CHFLT_COE10_7_0 - Filter coefficients for the first set of RX filter coefficients. +// MODEM_CHFLT_RX1_CHFLT_COE9_7_0 - Filter coefficients for the first set of RX filter coefficients. +// MODEM_CHFLT_RX1_CHFLT_COE8_7_0 - Filter coefficients for the first set of RX filter coefficients. +// MODEM_CHFLT_RX1_CHFLT_COE7_7_0 - Filter coefficients for the first set of RX filter coefficients. +// MODEM_CHFLT_RX1_CHFLT_COE6_7_0 - Filter coefficients for the first set of RX filter coefficients. +// MODEM_CHFLT_RX1_CHFLT_COE5_7_0 - Filter coefficients for the first set of RX filter coefficients. +// MODEM_CHFLT_RX1_CHFLT_COE4_7_0 - Filter coefficients for the first set of RX filter coefficients. +// MODEM_CHFLT_RX1_CHFLT_COE3_7_0 - Filter coefficients for the first set of RX filter coefficients. +// MODEM_CHFLT_RX1_CHFLT_COE2_7_0 - Filter coefficients for the first set of RX filter coefficients. +*/ +#define RF_MODEM_CHFLT_RX1_CHFLT_COE13_7_0_12 0x11, 0x21, 0x0C, 0x00, 0xFF, 0xBA, 0x0F, 0x51, 0xCF, 0xA9, 0xC9, 0xFC, 0x1B, 0x1E, 0x0F, 0x01 + +/* +// Set properties: RF_MODEM_CHFLT_RX1_CHFLT_COE1_7_0_12 +// Number of properties: 12 +// Group ID: 0x21 +// Start ID: 0x0C +// Default values: 0xFC, 0xFD, 0x15, 0xFF, 0x00, 0x0F, 0xFF, 0xC4, 0x30, 0x7F, 0xF5, 0xB5, +// Descriptions: +// MODEM_CHFLT_RX1_CHFLT_COE1_7_0 - Filter coefficients for the first set of RX filter coefficients. +// MODEM_CHFLT_RX1_CHFLT_COE0_7_0 - Filter coefficients for the first set of RX filter coefficients. +// MODEM_CHFLT_RX1_CHFLT_COEM0 - Filter coefficients for the first set of RX filter coefficients. +// MODEM_CHFLT_RX1_CHFLT_COEM1 - Filter coefficients for the first set of RX filter coefficients. +// MODEM_CHFLT_RX1_CHFLT_COEM2 - Filter coefficients for the first set of RX filter coefficients. +// MODEM_CHFLT_RX1_CHFLT_COEM3 - Filter coefficients for the first set of RX filter coefficients. +// MODEM_CHFLT_RX2_CHFLT_COE13_7_0 - Filter coefficients for the second set of RX filter coefficients. +// MODEM_CHFLT_RX2_CHFLT_COE12_7_0 - Filter coefficients for the second set of RX filter coefficients. +// MODEM_CHFLT_RX2_CHFLT_COE11_7_0 - Filter coefficients for the second set of RX filter coefficients. +// MODEM_CHFLT_RX2_CHFLT_COE10_7_0 - Filter coefficients for the second set of RX filter coefficients. +// MODEM_CHFLT_RX2_CHFLT_COE9_7_0 - Filter coefficients for the second set of RX filter coefficients. +// MODEM_CHFLT_RX2_CHFLT_COE8_7_0 - Filter coefficients for the second set of RX filter coefficients. +*/ +#define RF_MODEM_CHFLT_RX1_CHFLT_COE1_7_0_12 0x11, 0x21, 0x0C, 0x0C, 0xFC, 0xFD, 0x15, 0xFF, 0x00, 0x0F, 0xFF, 0xBA, 0x0F, 0x51, 0xCF, 0xA9 + +/* +// Set properties: RF_MODEM_CHFLT_RX2_CHFLT_COE7_7_0_12 +// Number of properties: 12 +// Group ID: 0x21 +// Start ID: 0x18 +// Default values: 0xB8, 0xDE, 0x05, 0x17, 0x16, 0x0C, 0x03, 0x00, 0x15, 0xFF, 0x00, 0x00, +// Descriptions: +// MODEM_CHFLT_RX2_CHFLT_COE7_7_0 - Filter coefficients for the second set of RX filter coefficients. +// MODEM_CHFLT_RX2_CHFLT_COE6_7_0 - Filter coefficients for the second set of RX filter coefficients. +// MODEM_CHFLT_RX2_CHFLT_COE5_7_0 - Filter coefficients for the second set of RX filter coefficients. +// MODEM_CHFLT_RX2_CHFLT_COE4_7_0 - Filter coefficients for the second set of RX filter coefficients. +// MODEM_CHFLT_RX2_CHFLT_COE3_7_0 - Filter coefficients for the second set of RX filter coefficients. +// MODEM_CHFLT_RX2_CHFLT_COE2_7_0 - Filter coefficients for the second set of RX filter coefficients. +// MODEM_CHFLT_RX2_CHFLT_COE1_7_0 - Filter coefficients for the second set of RX filter coefficients. +// MODEM_CHFLT_RX2_CHFLT_COE0_7_0 - Filter coefficients for the second set of RX filter coefficients. +// MODEM_CHFLT_RX2_CHFLT_COEM0 - Filter coefficients for the second set of RX filter coefficients. +// MODEM_CHFLT_RX2_CHFLT_COEM1 - Filter coefficients for the second set of RX filter coefficients. +// MODEM_CHFLT_RX2_CHFLT_COEM2 - Filter coefficients for the second set of RX filter coefficients. +// MODEM_CHFLT_RX2_CHFLT_COEM3 - Filter coefficients for the second set of RX filter coefficients. +*/ +#define RF_MODEM_CHFLT_RX2_CHFLT_COE7_7_0_12 0x11, 0x21, 0x0C, 0x18, 0xC9, 0xFC, 0x1B, 0x1E, 0x0F, 0x01, 0xFC, 0xFD, 0x15, 0xFF, 0x00, 0x0F + +/* +// Set properties: RF_PA_MODE_4 +// Number of properties: 4 +// Group ID: 0x22 +// Start ID: 0x00 +// Default values: 0x08, 0x7F, 0x00, 0x5D, +// Descriptions: +// PA_MODE - Selects the PA operating mode, and selects resolution of PA power adjustment (i.e., step size). +// PA_PWR_LVL - Configuration of PA output power level. +// PA_BIAS_CLKDUTY - Configuration of the PA Bias and duty cycle of the TX clock source. +// PA_TC - Configuration of PA ramping parameters. +*/ +#define RF_PA_MODE_4 0x11, 0x22, 0x04, 0x00, 0x08, 0x7F, 0x00, 0x1D + +/* +// Set properties: RF_SYNTH_PFDCP_CPFF_7 +// Number of properties: 7 +// Group ID: 0x23 +// Start ID: 0x00 +// Default values: 0x2C, 0x0E, 0x0B, 0x04, 0x0C, 0x73, 0x03, +// Descriptions: +// SYNTH_PFDCP_CPFF - Feed forward charge pump current selection. +// SYNTH_PFDCP_CPINT - Integration charge pump current selection. +// SYNTH_VCO_KV - Gain scaling factors (Kv) for the VCO tuning varactors on both the integrated-path and feed forward path. +// SYNTH_LPFILT3 - Value of resistor R2 in feed-forward path of loop filter. +// SYNTH_LPFILT2 - Value of capacitor C2 in feed-forward path of loop filter. +// SYNTH_LPFILT1 - Value of capacitors C1 and C3 in feed-forward path of loop filter. +// SYNTH_LPFILT0 - Bias current of the active amplifier in the feed-forward loop filter. +*/ +#define RF_SYNTH_PFDCP_CPFF_7 0x11, 0x23, 0x07, 0x00, 0x2C, 0x0E, 0x0B, 0x04, 0x0C, 0x73, 0x03 + +/* +// Set properties: RF_MATCH_VALUE_1_12 +// Number of properties: 12 +// Group ID: 0x30 +// Start ID: 0x00 +// Default values: 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +// Descriptions: +// MATCH_VALUE_1 - Match value to be compared with the result of logically AND-ing (bit-wise) the Mask 1 value with the received Match 1 byte. +// MATCH_MASK_1 - Mask value to be logically AND-ed (bit-wise) with the Match 1 byte. +// MATCH_CTRL_1 - Enable for Packet Match functionality, and configuration of Match Byte 1. +// MATCH_VALUE_2 - Match value to be compared with the result of logically AND-ing (bit-wise) the Mask 2 value with the received Match 2 byte. +// MATCH_MASK_2 - Mask value to be logically AND-ed (bit-wise) with the Match 2 byte. +// MATCH_CTRL_2 - Configuration of Match Byte 2. +// MATCH_VALUE_3 - Match value to be compared with the result of logically AND-ing (bit-wise) the Mask 3 value with the received Match 3 byte. +// MATCH_MASK_3 - Mask value to be logically AND-ed (bit-wise) with the Match 3 byte. +// MATCH_CTRL_3 - Configuration of Match Byte 3. +// MATCH_VALUE_4 - Match value to be compared with the result of logically AND-ing (bit-wise) the Mask 4 value with the received Match 4 byte. +// MATCH_MASK_4 - Mask value to be logically AND-ed (bit-wise) with the Match 4 byte. +// MATCH_CTRL_4 - Configuration of Match Byte 4. +*/ +#define RF_MATCH_VALUE_1_12 0x11, 0x30, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + +/* +// Set properties: RF_FREQ_CONTROL_INTE_8 +// Number of properties: 8 +// Group ID: 0x40 +// Start ID: 0x00 +// Default values: 0x3C, 0x08, 0x00, 0x00, 0x00, 0x00, 0x20, 0xFF, +// Descriptions: +// FREQ_CONTROL_INTE - Frac-N PLL Synthesizer integer divide number. +// FREQ_CONTROL_FRAC_2 - Frac-N PLL fraction number. +// FREQ_CONTROL_FRAC_1 - Frac-N PLL fraction number. +// FREQ_CONTROL_FRAC_0 - Frac-N PLL fraction number. +// FREQ_CONTROL_CHANNEL_STEP_SIZE_1 - EZ Frequency Programming channel step size. +// FREQ_CONTROL_CHANNEL_STEP_SIZE_0 - EZ Frequency Programming channel step size. +// FREQ_CONTROL_W_SIZE - Set window gating period (in number of crystal reference clock cycles) for counting VCO frequency during calibration. +// FREQ_CONTROL_VCOCNT_RX_ADJ - Adjust target count for VCO calibration in RX mode. +*/ +#define RF_FREQ_CONTROL_INTE_8 0x11, 0x40, 0x08, 0x00, 0x42, 0x0E, 0x14, 0x7A, 0xCC, 0xCD, 0x20, 0xFA + + +// AUTOMATICALLY GENERATED CODE! +// DO NOT EDIT/MODIFY BELOW THIS LINE! +// -------------------------------------------- + +#ifndef FIRMWARE_LOAD_COMPILE +#define RADIO_CONFIGURATION_DATA_ARRAY { \ + 0x07, RF_POWER_UP, \ + 0x08, RF_GPIO_PIN_CFG, \ + 0x06, RF_GLOBAL_XO_TUNE_2, \ + 0x05, RF_GLOBAL_CONFIG_1, \ + 0x06, RF_INT_CTL_ENABLE_2, \ + 0x08, RF_FRR_CTL_A_MODE_4, \ + 0x0D, RF_PREAMBLE_TX_LENGTH_9, \ + 0x0E, RF_SYNC_CONFIG_10, \ + 0x10, RF_PKT_CRC_CONFIG_12, \ + 0x10, RF_PKT_RX_THRESHOLD_12, \ + 0x10, RF_PKT_FIELD_3_CRC_CONFIG_12, \ + 0x10, RF_PKT_RX_FIELD_1_CRC_CONFIG_12, \ + 0x09, RF_PKT_RX_FIELD_4_CRC_CONFIG_5, \ + 0x08, RF_PKT_CRC_SEED_31_24_4, \ + 0x10, RF_MODEM_MOD_TYPE_12, \ + 0x05, RF_MODEM_FREQ_DEV_0_1, \ + 0x10, RF_MODEM_TX_RAMP_DELAY_12, \ + 0x10, RF_MODEM_BCR_NCO_OFFSET_2_12, \ + 0x07, RF_MODEM_AFC_LIMITER_1_3, \ + 0x05, RF_MODEM_AGC_CONTROL_1, \ + 0x10, RF_MODEM_AGC_WINDOW_SIZE_12, \ + 0x0E, RF_MODEM_RAW_CONTROL_10, \ + 0x06, RF_MODEM_RAW_SEARCH2_2, \ + 0x06, RF_MODEM_SPIKE_DET_2, \ + 0x05, RF_MODEM_RSSI_MUTE_1, \ + 0x09, RF_MODEM_DSA_CTRL1_5, \ + 0x10, RF_MODEM_CHFLT_RX1_CHFLT_COE13_7_0_12, \ + 0x10, RF_MODEM_CHFLT_RX1_CHFLT_COE1_7_0_12, \ + 0x10, RF_MODEM_CHFLT_RX2_CHFLT_COE7_7_0_12, \ + 0x08, RF_PA_MODE_4, \ + 0x0B, RF_SYNTH_PFDCP_CPFF_7, \ + 0x10, RF_MATCH_VALUE_1_12, \ + 0x0C, RF_FREQ_CONTROL_INTE_8, \ + 0x00 \ + } +#else +#define RADIO_CONFIGURATION_DATA_ARRAY { 0 } +#endif + +// DEFAULT VALUES FOR CONFIGURATION PARAMETERS +#define RADIO_CONFIGURATION_DATA_RADIO_XO_FREQ_DEFAULT 30000000L +#define RADIO_CONFIGURATION_DATA_CHANNEL_NUMBER_DEFAULT 0x00 +#define RADIO_CONFIGURATION_DATA_RADIO_PACKET_LENGTH_DEFAULT 0x10 +#define RADIO_CONFIGURATION_DATA_RADIO_STATE_AFTER_POWER_UP_DEFAULT 0x01 +#define RADIO_CONFIGURATION_DATA_RADIO_DELAY_CNT_AFTER_RESET_DEFAULT 0x1000 + +#define RADIO_CONFIGURATION_DATA_RADIO_PATCH_INCLUDED 0x00 +#define RADIO_CONFIGURATION_DATA_RADIO_PATCH_SIZE 0x00 +#define RADIO_CONFIGURATION_DATA_RADIO_PATCH { } + +#ifndef RADIO_CONFIGURATION_DATA_ARRAY +#error "This property must be defined!" +#endif + +#ifndef RADIO_CONFIGURATION_DATA_RADIO_XO_FREQ +#define RADIO_CONFIGURATION_DATA_RADIO_XO_FREQ RADIO_CONFIGURATION_DATA_RADIO_XO_FREQ_DEFAULT +#endif + +#ifndef RADIO_CONFIGURATION_DATA_CHANNEL_NUMBER +#define RADIO_CONFIGURATION_DATA_CHANNEL_NUMBER RADIO_CONFIGURATION_DATA_CHANNEL_NUMBER_DEFAULT +#endif + +#ifndef RADIO_CONFIGURATION_DATA_RADIO_PACKET_LENGTH +#define RADIO_CONFIGURATION_DATA_RADIO_PACKET_LENGTH RADIO_CONFIGURATION_DATA_RADIO_PACKET_LENGTH_DEFAULT +#endif + +#ifndef RADIO_CONFIGURATION_DATA_RADIO_STATE_AFTER_POWER_UP +#define RADIO_CONFIGURATION_DATA_RADIO_STATE_AFTER_POWER_UP RADIO_CONFIGURATION_DATA_RADIO_STATE_AFTER_POWER_UP_DEFAULT +#endif + +#ifndef RADIO_CONFIGURATION_DATA_RADIO_DELAY_CNT_AFTER_RESET +#define RADIO_CONFIGURATION_DATA_RADIO_DELAY_CNT_AFTER_RESET RADIO_CONFIGURATION_DATA_RADIO_DELAY_CNT_AFTER_RESET_DEFAULT +#endif + +#define RADIO_CONFIGURATION_DATA { \ + Radio_Configuration_Data_Array, \ + RADIO_CONFIGURATION_DATA_CHANNEL_NUMBER, \ + RADIO_CONFIGURATION_DATA_RADIO_PACKET_LENGTH, \ + RADIO_CONFIGURATION_DATA_RADIO_STATE_AFTER_POWER_UP, \ + RADIO_CONFIGURATION_DATA_RADIO_DELAY_CNT_AFTER_RESET \ + } + +#endif /* RADIO_CONFIG_H_ */ diff --git a/firmware/inc/driver/si4468.h b/firmware/inc/driver/si4468.h new file mode 100644 index 0000000..61e72e5 --- /dev/null +++ b/firmware/inc/driver/si4468.h @@ -0,0 +1,54 @@ +/** + * + * Author: Dylan Muller + * Copyright (c) 2025 + * All rights reserved. + * + * - Commercial/IP use prohibited. + * - Attribution required. + * See License.txt + * + */ + +#ifndef SI4468_H_ +#define SI4468_H_ + +#include "setup.h" + +#include <stdint.h> +#include <avr/io.h> + +#define SI4468_ID_RADIO 0xD1 + +#define SI4468_CMD_READ_CMD_BUFF 0x44 +#define SI4468_CMD_PART_INFO 0x01 +#define SI4468_CMD_FUNC_INFO 0x10 +#define SI4468_CMD_SET_PROPERTY 0x11 +#define SI4468_CMD_IRCAL 0x17 +#define SI4468_CMD_START_TX 0x31 +#define SI4468_CMD_CHANGE_STATE 0x34 + +#define SI4468_CTS 0xFF +#define SI4468_GET_RESP_LEN 0x2 + +#define SI4468_DEV_0 0 +#define SI4468_DEV_RADIO SI4468_DEV_0 +#define SI4468_DEV_0_PORT PORTB +#define SI4468_DEV_0_DDR DDRB +#define SI4468_DEV_0_SS PORTB2 + +typedef struct { + uint8_t chipRev; + uint16_t part; + uint8_t partBuild; + uint16_t id; + uint8_t customer; + uint8_t romId; ///< ROM ID (3 = revB1B, 6 = revC2A) +} si4468_info_t; + +void si4468_init(void); +void si4468_get_info(si4468_info_t* info); +void si4468_apply_startup_config(void); +void si4468_tx_mode(void); +void si4468_rx_mode(void); +#endif diff --git a/firmware/inc/module/drain.h b/firmware/inc/module/drain.h new file mode 100644 index 0000000..7b9d66d --- /dev/null +++ b/firmware/inc/module/drain.h @@ -0,0 +1,37 @@ +/** + * + * Author: Dylan Muller + * Copyright (c) 2025 + * All rights reserved. + * + * - Commercial/IP use prohibited. + * - Attribution required. + * See License.txt + * + */ + +#ifndef DRAIN_H_ +#define DRAIN_H_ + +#include <stdint.h> + +#define DRAIN_PROBE_START 0 // mV +#define DRAIN_PROBE_LIMIT 3000 +#define DRAIN_PROBE_INC_FINE 1 +#define DRAIN_PROBE_INC_COARSE 5 +#define DRAIN_PROBE_INC_THRESHOLD 100 +#define DRAIN_Q_AMP 100 // mA +#define DRAIN_TEST_COUNT 10 +#define DRAIN_TEST_BOUNDARY 10 +#define DRAIN_POWER_SAMPLES 10 +#define DRAIN_LOOP_DELAY_US 1000 +#define DRAIN_SETPOINT_TIMEOUT_MS 1500 +#define DRAIN_POWER_LOW_LIM 0 +#define DRAIN_POWER_HIGH_LIM 3000 +#define DRAIN_POWER_MODULUS 50 + +uint16_t drain_sweep_pwr( + int16_t target_fw_pwr +); + +#endif diff --git a/firmware/inc/module/gate.h b/firmware/inc/module/gate.h new file mode 100644 index 0000000..9f399c4 --- /dev/null +++ b/firmware/inc/module/gate.h @@ -0,0 +1,32 @@ +/** + * + * Author: Dylan Muller + * Copyright (c) 2025 + * All rights reserved. + * + * - Commercial/IP use prohibited. + * - Attribution required. + * See License.txt + * + */ + +#ifndef GATE_H_ +#define GATE_H_ + +#include <stdint.h> +#include <stdbool.h> +#include <util/delay.h> + +#define GATE_PROBE_START 2800 // mV +#define GATE_PROBE_LIMIT 3300 // mV +#define GATE_PROBE_DRAIN 1000 // mV +#define GATE_PROBE_INC 1 // COUNTS +#define GATE_PA_POWER_DOWN 1 +#define GATE_LOOP_DELAY_US 1000 + +uint16_t gate_probe( + uint16_t target_amp, // mA + uint16_t* probe_result +); + +#endif diff --git a/firmware/inc/peripheral/ring.h b/firmware/inc/peripheral/ring.h new file mode 100644 index 0000000..d2a713d --- /dev/null +++ b/firmware/inc/peripheral/ring.h @@ -0,0 +1,77 @@ +/** + * + * Author: Dylan Muller + * Copyright (c) 2025 + * All rights reserved. + * + * - Commercial/IP use prohibited. + * - Attribution required. + * See License.txt + * + */ + +#ifndef RING_H_ +#define RING_H_ + +#include <stdbool.h> +#include <stddef.h> +#include <stdint.h> + +typedef struct +{ + uint8_t *buf; + uint8_t *end; + uint8_t *write; + uint8_t *read; +} ring_t; + +#define RING_INIT(buf_, len_) \ + ((ring_t){ \ + .buf = (buf_), \ + .end = (buf_)+(len_), \ + .write = (buf_), \ + .read = (buf_)} \ + ) + +ring_t ring_init( + uint8_t *buf, + size_t len +); + +bool ring_is_empty( + ring_t ring +); + +bool ring_is_full( + ring_t ring +); + +size_t ring_push_available( + ring_t ring +); + +size_t ring_pop_available( + ring_t ring +); + +bool ring_push( + ring_t *ring, + uint8_t data +); + +bool ring_push_over( + ring_t *ring, + uint8_t data +); + +bool ring_pop( + ring_t *ring, + uint8_t *data +); + +bool ring_peek( + ring_t *ring, + uint8_t *data +); + +#endif diff --git a/firmware/inc/peripheral/spi.h b/firmware/inc/peripheral/spi.h new file mode 100644 index 0000000..003fc04 --- /dev/null +++ b/firmware/inc/peripheral/spi.h @@ -0,0 +1,34 @@ +/** + * + * Author: Dylan Muller + * Copyright (c) 2025 + * All rights reserved. + * + * - Commercial/IP use prohibited. + * - Attribution required. + * See License.txt + * + */ + +#ifndef SPI_H_ +#define SPI_H_ + +#include <stdbool.h> +#include <stddef.h> +#include <stdint.h> + +void spi_init(void); + +bool spi_busy(void); + +void spi_flush(void); + +void spi_start( + uint8_t *out, + uint8_t *in, + size_t len, + uint8_t *port, + uint8_t pin +); + +#endif diff --git a/firmware/inc/peripheral/timer.h b/firmware/inc/peripheral/timer.h new file mode 100644 index 0000000..ff45c85 --- /dev/null +++ b/firmware/inc/peripheral/timer.h @@ -0,0 +1,22 @@ +/** + * + * Author: Dylan Muller + * Copyright (c) 2025 + * All rights reserved. + * + * - Commercial/IP use prohibited. + * - Attribution required. + * See License.txt + * + */ + +#ifndef TIMER_H_ +#define TIMER_H_ + +#include <stdint.h> + +void timer_init(void); +void timer_reset(void); +uint32_t timer_millis(void); + +#endif diff --git a/firmware/inc/peripheral/twi.h b/firmware/inc/peripheral/twi.h new file mode 100644 index 0000000..8f08777 --- /dev/null +++ b/firmware/inc/peripheral/twi.h @@ -0,0 +1,35 @@ +/** + * + * Author: Dylan Muller + * Copyright (c) 2025 + * All rights reserved. + * + * - Commercial/IP use prohibited. + * - Attribution required. + * See License.txt + * + */ + +#ifndef TWI_H_ +#define TWI_H_ + +#include <stdbool.h> +#include <stddef.h> +#include <stdint.h> + +#define TWI_ADDRESS_W(x) (((x) << 1) & ~0x01) +#define TWI_ADDRESS_R(x) (((x) << 1) | 0x01) + +void twi_init(void); + +bool twi_busy(void); + +void twi_flush(void); + +void twi_start( + uint8_t address, + uint8_t *data, + size_t len +); + +#endif diff --git a/firmware/inc/peripheral/uart.h b/firmware/inc/peripheral/uart.h new file mode 100644 index 0000000..e2a0f3d --- /dev/null +++ b/firmware/inc/peripheral/uart.h @@ -0,0 +1,56 @@ +/** + * + * Author: Dylan Muller + * Copyright (c) 2025 + * All rights reserved. + * + * - Commercial/IP use prohibited. + * - Attribution required. + * See License.txt + * + */ + +#ifndef UARTINT_H_ +#define UARTINT_H_ + +#include <stddef.h> +#include <stdint.h> +#include <stdio.h> +#include <stdbool.h> + +extern FILE uart_out; +extern FILE uart_in; + +void uart_init(void); + +bool uart_tx( + uint8_t data +); + +bool uart_rx( + uint8_t* data +); + +size_t uart_tx_burst( + uint8_t* data, + size_t size +); + +size_t uart_rx_burst( + uint8_t* data, + size_t size +); + +size_t uart_tx_available(void); + +size_t uart_rx_available(void); + +bool uart_rx_peek( + uint8_t* data +); + +void uart_tx_flush(void); + +char *uart_ngets(char *s, size_t n); + +#endif diff --git a/firmware/inc/setup.h b/firmware/inc/setup.h new file mode 100644 index 0000000..e01bcd3 --- /dev/null +++ b/firmware/inc/setup.h @@ -0,0 +1,39 @@ +/** + * + * Author: Dylan Muller + * Copyright (c) 2025 + * All rights reserved. + * + * - Commercial/IP use prohibited. + * - Attribution required. + * See License.txt + * + */ + +/* Global Peripheral Configuration*/ + +#define __AVR_ATmega328__ + +#define F_CPU 8000000UL + +#define BAUD 19200 +#define UART_BUF_SIZE 25 +#define UART_OVERWRITE + +#define TWI_FREQUENCY 350000 +#define TWI_PRESCALER 1 +#define TWPS0_VALUE 0 +#define TWPS1_VALUE 0 + +#define SPI_FREQUENCY 500000 +#define SPI_PRESCALER 16 +#define SPR0_VALUE 1 +#define SPR1_VALUE 0 +#define SPI2X_VALUE 0 +#define SPI_MODE 0 +#define SPI_DORD 0 + +#define TRANSACT_DELAY_MS 5 +#define INIT_DELAY_MS 10 + +#define SYS_VER_STR "1.01.5" diff --git a/firmware/inc/status.h b/firmware/inc/status.h new file mode 100644 index 0000000..b9c647b --- /dev/null +++ b/firmware/inc/status.h @@ -0,0 +1,83 @@ +/** + * + * Author: Dylan Muller + * Copyright (c) 2025 + * All rights reserved. + * + * - Commercial/IP use prohibited. + * - Attribution required. + * See License.txt + * + */ + +#ifndef STATUS_H_ +#define STATUS_H_ + +#include <stdint.h> +#include <avr/pgmspace.h> + +extern const char* const gate_lut[]; +extern const char* const drain_lut[]; +extern const char* const system_lut[]; + +enum +{ + GATE_STATUS_INACTIVE = 0, + GATE_STATUS_PROBE_ERROR, + GATE_STATUS_PROBE_SUCCESS, + GATE_STATUS_PROBE_TIMEOUT +}; + +typedef struct { + uint8_t status; + uint16_t q_volt; + uint16_t q_amp; + uint16_t q_time; + uint16_t v_set; + uint16_t q_drain; + uint8_t func; +} t_gate_status; + +enum +{ + DRAIN_STATUS_INACTIVE = 0, + DRAIN_STATUS_POWER_CONTROL, + DRAIN_STATUS_OVERRIDE, + DRAIN_STATUS_ADC_ERROR, + DRAIN_STATUS_CURRENT_ALARM +}; + +typedef struct { + uint8_t status; + uint16_t v_set; + uint16_t v_adc; + uint16_t amp; + uint8_t func; +} t_drain_status; + +enum +{ + SYSTEM_STATUS_IDLE = 0, + SYSTEM_STATUS_BUSY, + SYSTEM_STATUS_LOCKED, + SYSTEM_STATUS_SETPOINT_FAIL, + SYSTEM_STATUS_SETPOINT_REACHED, + SYSTEM_STATUS_SETPOINT_TIMEOUT, + SYSTEM_STATUS_VSWR_ALARM +}; + +typedef struct { + uint8_t status; + uint16_t v_fw; + int16_t p_fw; + uint16_t v_rev; + int16_t p_rev; + uint16_t swr; + uint16_t swr_lim; + uint16_t atten; + uint8_t p_strat; + int16_t p_set; + uint16_t d_time; +} t_system_status; + +#endif diff --git a/firmware/inc/util.h b/firmware/inc/util.h new file mode 100644 index 0000000..5936a3a --- /dev/null +++ b/firmware/inc/util.h @@ -0,0 +1,46 @@ +/** + * + * Author: Dylan Muller + * Copyright (c) 2025 + * All rights reserved. + * + * - Commercial/IP use prohibited. + * - Attribution required. + * See License.txt + * + */ + +#ifndef UTIL_H_ +#define UTIL_H_ + +#include <stdint.h> + +#define UTIL_SYSTEM_VOLT ((uint32_t)3300) // (mV) +#define UTIL_CONV_BITS 12 +#define UTIL_CONV_BIT(x) (1 << x) + +#define UTIL_COUPLER_ATTEN ((int16_t)4250) // BI-DIR COUPL CAL +#define UTIL_POWER_THRESHOLD 2000 + +uint8_t util_volt_to_count( + uint16_t volt, + uint16_t* count +); + +uint8_t util_count_to_volt( + uint16_t count, + uint16_t* volt +); + +int8_t util_count_to_pwr( + uint16_t count, + int16_t* cpwr +); + +void util_print_pwr( + int16_t cpwr +); + +uint16_t util_get_free_mem(void); + +#endif diff --git a/firmware/src/bsp.c b/firmware/src/bsp.c new file mode 100644 index 0000000..fdb8a39 --- /dev/null +++ b/firmware/src/bsp.c @@ -0,0 +1,38 @@ +/** + * + * Author: Dylan Muller + * Copyright (c) 2025 + * All rights reserved. + * + * - Commercial/IP use prohibited. + * - Attribution required. + * See License.txt + * + */ + +#include "setup.h" +#include "bsp.h" + +#include <stdlib.h> +#include <stdio.h> +#include <avr/io.h> +#include <util/delay.h> +#include <avr/interrupt.h> +#include <avr/wdt.h> + +void bsp_soft_reset(void) +{ + cli(); + + MCUSR &= ~(1 << WDRF); + + WDTCSR = (1 << WDCE) | (1 << WDE); + WDTCSR = (1 << WDP1); + WDTCSR = WDTCSR | 0x40; + + MCUSR &= ~(1 << WDRF); + + sei(); + + while(1){}; +} diff --git a/firmware/src/cmd.c b/firmware/src/cmd.c new file mode 100644 index 0000000..f55ed80 --- /dev/null +++ b/firmware/src/cmd.c @@ -0,0 +1,27 @@ +/** + * + * Author: Dylan Muller + * Copyright (c) 2025 + * All rights reserved. + * + * - Commercial/IP use prohibited. + * - Attribution required. + * See License.txt + * + */ + +#include "cmd.h" + +#include <avr/pgmspace.h> + +const char* const cmd_lut[CMD_SIZE][CMD_ENTRY_SIZE] PROGMEM = { + {CMD_POWER_GET_STR, CMD_POWER_GET_DESC}, + {CMD_POWER_SET_STR, CMD_POWER_SET_DESC}, + {CMD_TX_STR, CMD_TX_DESC}, + {CMD_RX_STR, CMD_RX_DESC}, + {CMD_DRAIN_SET_STR, CMD_DRAIN_SET_DESC}, + {CMD_PROBE_STR, CMD_PROBE_DESC}, + {CMD_RESET_STR, CMD_RESET_DESC}, + {CMD_REPORT_STR, CMD_REPORT_DESC}, + {CMD_HELP_STR, CMD_HELP_DESC} + }; diff --git a/firmware/src/driver/f1956.c b/firmware/src/driver/f1956.c new file mode 100644 index 0000000..3af5fba --- /dev/null +++ b/firmware/src/driver/f1956.c @@ -0,0 +1,61 @@ +/** + * + * Author: Dylan Muller + * Copyright (c) 2025 + * All rights reserved. + * + * - Commercial/IP use prohibited. + * - Attribution required. + * See License.txt + * + */ + +#include "setup.h" + +#include "peripheral/spi.h" +#include "driver/f1956.h" + +#include <avr/io.h> +#include <avr/interrupt.h> +#include <util/delay.h> + +void att_init(uint8_t init_value) +{ + F1956_DEV_0_DDR |= (1 << F1956_DEV_0_SS); + F1956_DEV_0_PORT |= (1 << F1956_DEV_0_SS); + + att_set(F1956_ID_INPUT_ATT, init_value); + _delay_ms(10); +} + +void att_set( + uint8_t id, + uint8_t value +) +{ + uint8_t dev_id = 0x0; + uint8_t dev_ss = 0x0; + uint8_t* dev_port = 0x0; + uint8_t cmd_buf[2] = {0x0, 0x0}; + + switch (id) + { + case F1956_ID_INPUT_ATT: + dev_id = F1956_DEV_INPUT_ATT; + break; + } + + switch (dev_id) + { + case F1956_DEV_INPUT_ATT: + dev_ss = F1956_DEV_0_SS; + dev_port = (uint8_t*)&F1956_DEV_0_PORT; + break; + } + + cmd_buf[0] = value & 0x7F; + cmd_buf[1] = F1956_DEV_INPUT_ATT_ADDR; + + spi_start(cmd_buf, cmd_buf, sizeof(cmd_buf), dev_port, dev_ss); + spi_flush(); +} diff --git a/firmware/src/driver/mcp3202.c b/firmware/src/driver/mcp3202.c new file mode 100644 index 0000000..07f84db --- /dev/null +++ b/firmware/src/driver/mcp3202.c @@ -0,0 +1,129 @@ +/** + * + * Author: Dylan Muller + * Copyright (c) 2025 + * All rights reserved. + * + * - Commercial/IP use prohibited. + * - Attribution required. + * See License.txt + * + */ + +#include "setup.h" + +#include "peripheral/spi.h" +#include "driver/mcp3202.h" + +#include <avr/io.h> +#include <avr/interrupt.h> +#include <util/delay.h> + +void adc_init(void) +{ + MCP3202_DEV_0_DDR |= (1 << MCP3202_DEV_0_SS); + MCP3202_DEV_1_DDR |= (1 << MCP3202_DEV_1_SS); + + MCP3202_DEV_0_PORT &= ~(1 << MCP3202_DEV_0_SS); + MCP3202_DEV_1_PORT &= ~(1 << MCP3202_DEV_1_SS); + + _delay_ms(TRANSACT_DELAY_MS); + + MCP3202_DEV_0_PORT |= (1 << MCP3202_DEV_0_SS); + MCP3202_DEV_1_PORT |= (1 << MCP3202_DEV_1_SS); + + _delay_ms(TRANSACT_DELAY_MS); +} + +uint16_t adc_read( + uint8_t id, + uint8_t conv_bypass +) +{ + uint8_t dev_id = 0x0; + uint8_t dev_ch = 0x0; + uint8_t dev_ss = 0x0; + uint8_t* dev_port = 0x0; + uint8_t cmd_buf[3] = {0x0, 0x0, 0x0}; + uint16_t adc_daq = 0x0; + + switch(id) + { + case MCP3202_ID_FW_POWER: + dev_id = MCP3202_DEV_FW_POWER; + dev_ch = MCP3202_CHN_FW_POWER; + break; + + case MCP3202_ID_REV_POWER: + dev_id = MCP3202_DEV_REV_POWER; + dev_ch = MCP3202_CHN_REV_POWER; + break; + + case MCP3202_ID_DRAIN_VOLT: + dev_id = MCP3202_DEV_DRAIN_VOLT; + dev_ch = MCP3202_CHN_DRAIN_VOLT; + break; + + case MCP3202_ID_DRAIN_AMP: + dev_id = MCP3202_DEV_DRAIN_AMP; + dev_ch = MCP3202_CHN_DRAIN_AMP; + break; + } + + switch(dev_id) + { + case MCP3202_DEV_0: + dev_port = (uint8_t*)&MCP3202_DEV_0_PORT; + dev_ss = MCP3202_DEV_0_SS; + break; + + case MCP3202_DEV_1: + dev_port = (uint8_t*)&MCP3202_DEV_1_PORT; + dev_ss = MCP3202_DEV_1_SS; + break; + } + + cmd_buf[0] = MCP3202_REQ_START; + cmd_buf[1] = (dev_ch == MCP3202_CHN_0) ? MCP3202_REQ_CH0 : MCP3202_REQ_CH1; + cmd_buf[2] = MCP3202_REQ_PAD; + + spi_start(cmd_buf, cmd_buf, sizeof(cmd_buf), dev_port, dev_ss); + spi_flush(); + + adc_daq = (uint16_t)(cmd_buf[MCP3202_DAQ_MSB]); + adc_daq |= ((uint16_t)(cmd_buf[MCP3202_DAQ_LSB] & 0xF) << 8); + adc_daq = adc_daq & 0xFFF; + + if (conv_bypass == 0) + { + switch(id) + { + case MCP3202_ID_DRAIN_VOLT: + adc_daq = (uint32_t)(((uint32_t)adc_daq * MCP3202_DRAIN_VOLT_GAIN)/10); + break; + case MCP3202_ID_DRAIN_AMP: + adc_daq = (uint32_t)(((uint32_t)adc_daq * 10)/MCP3202_DRAIN_AMP_GAIN); + break; + } + } + + return (uint16_t)adc_daq; +} + +uint16_t adc_read_n( + uint8_t id, + uint8_t n +) +{ + uint32_t x = 0; + uint8_t i = 0; + + for (i = 0; i < n; i++) + { + x += adc_read(id, 0); + } + + x /= n; + + return (uint16_t)x; +} diff --git a/firmware/src/driver/mcp4725.c b/firmware/src/driver/mcp4725.c new file mode 100644 index 0000000..4cb9bd6 --- /dev/null +++ b/firmware/src/driver/mcp4725.c @@ -0,0 +1,101 @@ +/** + * + * Author: Dylan Muller + * Copyright (c) 2025 + * All rights reserved. + * + * - Commercial/IP use prohibited. + * - Attribution required. + * See License.txt + * + */ + +#include "setup.h" + +#include "peripheral/twi.h" +#include "driver/mcp4725.h" + +#include <avr/io.h> +#include <avr/interrupt.h> +#include <util/delay.h> + +void dac_init(uint16_t init_value) +{ + dac_write(MCP4725_ID_GATE_VOLT, init_value, 0); + dac_write(MCP4725_ID_DRAIN_VOLT, init_value, 0); + + _delay_ms(TRANSACT_DELAY_MS); +} + +void dac_write( + uint8_t id, + uint16_t value, + uint8_t conv_bypass +) +{ + uint8_t dev_addr = 0x0; + uint8_t cmd_buf[2] = {0x0, 0x0}; + uint8_t drain_mode = 0x0; + + switch(id) + { + case MCP4725_ID_GATE_VOLT: + dev_addr = TWI_ADDRESS_W(MCP4725_DEV_GATE_VOLT_ADDR); + break; + case MCP4725_ID_DRAIN_VOLT: + dev_addr = TWI_ADDRESS_W(MCP4725_DEV_DRAIN_VOLT_ADDR); + drain_mode = 1; + break; + } + + if (conv_bypass == 0) + { + if (drain_mode == 1) + { + value = (uint16_t)(((uint32_t)value * 10)/MCP4725_DRAIN_GAIN); + } + } + + cmd_buf[0] = ((value >> 8) & 0xF) | MCP4725_BIT_PD0(0) | MCP4725_BIT_PD1(0); + cmd_buf[1] = value & 0xFF; + + twi_start(dev_addr, cmd_buf, sizeof(cmd_buf)); + twi_flush(); +} + +uint16_t dac_read( + uint8_t id, + uint8_t conv_bypass +) +{ + uint8_t dev_addr = 0x0; + uint8_t cmd_buf[3] = {0x0, 0x0, 0x0}; + uint16_t value = 0x0; + uint8_t drain_mode = 0x0; + + switch(id) + { + case MCP4725_ID_GATE_VOLT: + dev_addr = TWI_ADDRESS_R(MCP4725_DEV_GATE_VOLT_ADDR); + break; + case MCP4725_ID_DRAIN_VOLT: + dev_addr = TWI_ADDRESS_R(MCP4725_DEV_DRAIN_VOLT_ADDR); + drain_mode = 1; + break; + } + + twi_start(dev_addr, cmd_buf, sizeof(cmd_buf)); + twi_flush(); + + value = (((uint16_t)cmd_buf[1]) << 4) | (cmd_buf[2] >> 4); + + if (conv_bypass == 0) + { + if (drain_mode) + { + value = (uint16_t)(((uint32_t)value * MCP4725_DRAIN_GAIN)/10); + } + } + + return (value & 0xFFF); +} diff --git a/firmware/src/driver/si4468.c b/firmware/src/driver/si4468.c new file mode 100644 index 0000000..17dd77d --- /dev/null +++ b/firmware/src/driver/si4468.c @@ -0,0 +1,201 @@ +/** + * + * Author: Dylan Muller + * Copyright (c) 2025 + * All rights reserved. + * + * - Commercial/IP use prohibited. + * - Attribution required. + * See License.txt + * + */ + +#include "setup.h" + +#include "peripheral/spi.h" + +#include "driver/si4468.h" +#include "driver/radio_config.h" +#include "driver/device.h" + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +#include <avr/io.h> +#include <avr/interrupt.h> +#include <util/delay.h> +#include <util/atomic.h> +#include <avr/pgmspace.h> + + +static const uint8_t config[] PROGMEM = RADIO_CONFIGURATION_DATA_ARRAY; + +void si4468_init(void) +{ + SI4468_DEV_0_DDR |= (1 << SI4468_DEV_0_SS); + SI4468_DEV_0_PORT |= (1 << SI4468_DEV_0_SS); +} + +void si44468_get_device( + int id, + t_dev* device +) +{ + uint8_t dev_id = 0x0; + uint8_t dev_ss = 0x0; + uint8_t* dev_port = 0x0; + + device->dev_id = 0; + device->dev_ss = 0; + device->dev_port = 0; + + switch (id) + { + case SI4468_ID_RADIO: + dev_id = SI4468_DEV_RADIO; + break; + } + + switch (dev_id) + { + case SI4468_DEV_RADIO: + dev_ss = SI4468_DEV_0_SS; + dev_port = (uint8_t*)&SI4468_DEV_0_PORT; + break; + } + + device->dev_id = dev_id; + device->dev_ss = dev_ss; + device->dev_port = dev_port; +} + +static uint8_t si4468_get_response( + void* buf, + uint8_t len +) +{ + t_dev device; + uint8_t cts = 0x0; + uint8_t* cmd_buf = 0x0; + uint16_t cmd_size = 0x0; + uint8_t i = 0; + + si44468_get_device(SI4468_ID_RADIO, &device); + + cmd_size = len + SI4468_GET_RESP_LEN; + cmd_buf = (uint8_t*)malloc((cmd_size)); + + cmd_buf[0] = SI4468_CMD_READ_CMD_BUFF; + cmd_buf[1] = SI4468_CTS; + + spi_start(cmd_buf, cmd_buf, SI4468_GET_RESP_LEN, device.dev_port, device.dev_ss); + spi_flush(); + + cts = (cmd_buf[0] == SI4468_CTS); + + if(cts) + { + if (len > 0) + { + for(i = 0x0; i < cmd_size; i++) + { + cmd_buf[i] = SI4468_CTS; + } + + cmd_buf[0] = SI4468_CMD_READ_CMD_BUFF; + + spi_start(cmd_buf, cmd_buf, cmd_size, (uint8_t*)&SI4468_DEV_0_PORT, SI4468_DEV_0_SS); + spi_flush(); + + for(i = SI4468_GET_RESP_LEN; i < cmd_size; i++) + { + ((uint8_t*)buf)[i - SI4468_GET_RESP_LEN] = cmd_buf[i]; + } + + } + } + + free(cmd_buf); + + return cts; +} + +static uint8_t si4468_wait_for_response( + void* buf, + uint8_t buf_len +) +{ + while(!si4468_get_response(buf, buf_len)) + { + _delay_ms(10); + } + + return 1; +} + +static void si4468_exec_api( + void* in, + size_t in_len, + void* out, + uint8_t out_len +) +{ + t_dev device; + si44468_get_device(SI4468_ID_RADIO, &device); + + if (si4468_wait_for_response(0, 0)) + { + spi_start(in, 0, in_len, device.dev_port, device.dev_ss); + spi_flush(); + + if (out != 0) + { + si4468_wait_for_response(out, out_len); + } + } +} + +void si4468_apply_startup_config(void) +{ + uint16_t i = 0; + uint8_t buf[100]; + + for(i = 0; i < sizeof(config); i++) + { + memcpy_P(buf, &config[i], sizeof(buf)); + uint8_t tmp = buf[0]; + si4468_exec_api(&buf[1], tmp, 0, 0); + i += tmp; + } +} + +void si4468_get_info( + si4468_info_t* info +) +{ + uint8_t data[8] = { + SI4468_CMD_PART_INFO + }; + + si4468_exec_api(data, 1, data, 8); + + info->chipRev = data[0]; + info->part = (data[1]<<8) | data[2]; + info->partBuild = data[3]; + info->id = (data[4]<<8) | data[5]; + info->customer = data[6]; + info->romId = data[7]; +} + +void si4468_tx_mode(void) +{ + uint8_t packet[] = {SI4468_CMD_START_TX, 0,0,0, 0,0,0 }; + si4468_exec_api(packet, sizeof(packet), 0, 0); +} + +void si4468_rx_mode(void) +{ + uint8_t packet[] = {SI4468_CMD_CHANGE_STATE, 0x3}; + si4468_exec_api(packet, sizeof(packet), 0, 0); +} diff --git a/firmware/src/main.c b/firmware/src/main.c new file mode 100644 index 0000000..02d103d --- /dev/null +++ b/firmware/src/main.c @@ -0,0 +1,343 @@ +/**
+ *
+ * Author: Dylan Muller
+ * Copyright (c) 2025
+ * All rights reserved.
+ *
+ * - Commercial/IP use prohibited.
+ * - Attribution required.
+ * See License.txt
+ *
+ */
+
+#include "setup.h"
+
+#include "peripheral/timer.h"
+#include "peripheral/uart.h"
+#include "peripheral/twi.h"
+#include "peripheral/spi.h"
+
+#include "driver/mcp3202.h"
+#include "driver/mcp4725.h"
+#include "driver/f1956.h"
+#include "driver/si4468.h"
+
+#include "module/gate.h"
+#include "module/drain.h"
+
+#include "cmd.h"
+#include "bsp.h"
+#include "status.h"
+#include "util.h"
+
+#include <avr/io.h>
+#include <util/delay.h>
+#include <avr/interrupt.h>
+#include <avr/pgmspace.h>
+#include <avr/wdt.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdbool.h>
+
+extern t_gate_status gate_status;
+extern t_drain_status drain_status;
+extern t_system_status system_status;
+
+void system_info(void)
+{
+ CMD_PRINT("SYSTEM BOOT v" SYS_VER_STR);
+ CMD_PRINT("SYSTEM INIT");
+ printf("%d BYTES AVAILABLE\n", util_get_free_mem());
+}
+
+void setup(void)
+{
+ cli();
+
+ gate_status.status = GATE_STATUS_INACTIVE;
+ drain_status.status = DRAIN_STATUS_INACTIVE;
+ system_status.status = SYSTEM_STATUS_IDLE;
+
+ wdt_reset();
+ wdt_disable();
+
+ timer_init();
+
+ uart_init();
+ twi_init();
+ spi_init();
+
+ sei();
+
+ _delay_ms(INIT_DELAY_MS);
+
+ si4468_init();
+
+ adc_init();
+ att_init(0);
+ dac_init(0);
+
+ _delay_ms(INIT_DELAY_MS);
+
+ si4468_apply_startup_config();
+
+ _delay_ms(INIT_DELAY_MS);
+
+ si4468_rx_mode();
+}
+
+void report_system_status()
+{
+ uint16_t gate_v_set = 0x0;
+ uint16_t gate_v_count = 0x0;
+
+ uint16_t drain_v_set = 0x0;
+ uint16_t drain_v_adc = 0x0;
+ uint16_t drain_amp_count = 0x0;
+ uint16_t drain_amp = 0x0;
+ uint16_t drain_v_count = 0x0;
+
+ uint16_t fw_pwr_adc = 0x0;
+ uint16_t fw_pwr_volt = 0x0;
+ int16_t fw_pwr = 0x0;
+
+ // gate status
+
+ gate_status.q_drain = GATE_PROBE_DRAIN;
+ gate_v_count = dac_read(MCP4725_ID_GATE_VOLT, 0);
+ util_count_to_volt(gate_v_count, &gate_v_set);
+ gate_status.v_set = gate_v_set;
+
+
+ printf_P(PSTR("- GATE -\n"));
+ printf_P(PSTR("STATUS : %s\n"),
+ pgm_read_word(&gate_lut[gate_status.status]));
+ printf_P(PSTR("Q-VOLT (mV) : %d\n"), gate_status.q_volt);
+ printf_P(PSTR("Q-AMP (mA) : %d\n"), gate_status.q_amp);
+ printf_P(PSTR("Q-TIME (ms) : %d\n"), gate_status.q_time);
+ printf_P(PSTR("V-SET (mV) : %d\n"), gate_status.v_set);
+ printf_P(PSTR("Q-DRAIN (mV) : %d\n"), gate_status.q_drain);
+
+ // drain status
+ drain_v_count = dac_read(MCP4725_ID_DRAIN_VOLT, 0);
+ util_count_to_volt(drain_v_count, &drain_v_set);
+ drain_status.v_set = drain_v_set;
+
+ drain_v_count = adc_read(MCP3202_ID_DRAIN_VOLT, 0);
+ util_count_to_volt(drain_v_count, &drain_v_adc);
+ drain_status.v_adc = drain_v_adc;
+
+ drain_amp_count = adc_read(MCP3202_ID_DRAIN_AMP, 0);
+ util_count_to_volt(drain_amp_count, &drain_amp);
+ drain_status.amp = drain_amp;
+
+ printf_P(PSTR("- DRAIN -\n"));
+ printf_P(PSTR("STATUS : %s\n"),
+ pgm_read_word(&drain_lut[drain_status.status]));
+ printf_P(PSTR("V-ADC (mV) : %d\n"), drain_status.v_adc);
+ printf_P(PSTR("V-SET (mV) : %d\n"), drain_status.v_set);
+ printf_P(PSTR("AMP (mA) : %d\n"), drain_status.amp);
+
+ // system status
+ fw_pwr_adc = adc_read_n(MCP3202_ID_FW_POWER, DRAIN_POWER_SAMPLES);
+ util_count_to_volt(fw_pwr_adc, &fw_pwr_volt);
+ util_count_to_pwr(fw_pwr_adc, &fw_pwr);
+ system_status.v_fw = fw_pwr_volt;
+ system_status.p_fw = fw_pwr;
+
+ printf_P(PSTR("- SYSTEM -\n"));
+ printf_P(PSTR("STATUS : %s\n"),
+ pgm_read_word(&system_lut[system_status.status]));
+ printf_P(PSTR("V-FWD (mV) : %d\n"), system_status.v_fw);
+ printf_P(PSTR("P-FWD (cdBm) : %d\n"), system_status.p_fw);
+ printf_P(PSTR("P-SET (cdBm) : %d\n"), system_status.p_set);
+ printf_P(PSTR("T-DELTA (ms) : %d\n"), system_status.d_time);
+}
+
+void loop()
+{
+ char uart_buffer[UART_BUF_SIZE];
+ char cmd_buffer[UART_BUF_SIZE];
+ char* cmd_tok = 0x0;
+ int16_t argv[CMD_MAX_ARGS];
+ uint16_t argc = 0x0;
+ bool gate_probed = false;
+
+ while (1)
+ {
+ cmd_tok = 0x0;
+ argc = 0x0;
+
+ if(uart_ngets(uart_buffer, UART_BUF_SIZE))
+ {
+ cmd_tok = strtok(uart_buffer, " ");
+ strcpy(cmd_buffer, cmd_tok);
+
+ while ((cmd_tok = strtok(NULL, " ")) != NULL) {
+ argv[argc++] = atoi(cmd_tok);
+ }
+
+ if (CMD_SWITCH(CMD_REPORT, uart_buffer))
+ {
+ CMD_PRINT("DUMP SYSTEM REPORT");
+ report_system_status();
+ }
+
+ else if (CMD_SWITCH(CMD_POWER_GET, uart_buffer))
+ {
+ CMD_PRINT("DUMP POWER ADC");
+ uint16_t fw_pwr_adc = adc_read_n(MCP3202_ID_FW_POWER,10);
+ CMD_PRINT_FMT("%d", fw_pwr_adc);
+ }
+
+ else if (CMD_SWITCH(CMD_PROBE, uart_buffer))
+ {
+ uint16_t gate_probe_count = 0x0;
+ uint16_t drain_current = 0x0;
+ uint32_t time_start = 0x0;
+ uint16_t time_delta = 0x0;
+
+ if (!gate_probed)
+ {
+ CMD_PRINT("STARTING Q-PROBE");
+ CMD_PRINT_FMT("DRAIN_Q_AMP = %d mA", DRAIN_Q_AMP);
+
+ time_start = timer_millis();
+
+ si4468_rx_mode();
+ drain_current = gate_probe(DRAIN_Q_AMP, &gate_probe_count);
+
+ time_delta = (uint16_t)(timer_millis() - time_start);
+ gate_status.q_time = time_delta;
+
+ CMD_PRINT_FMT("PROBE COMPLETED IN %d ms", time_delta);
+
+ if (drain_current >= DRAIN_Q_AMP)
+ {
+ gate_status.status = GATE_STATUS_PROBE_SUCCESS;
+ CMD_PRINT_FMT("Q-PROBE SUCCEEDED, IQ = %d mA", drain_current);
+ gate_probed = true;
+ }
+ else
+ {
+ gate_status.status = GATE_STATUS_PROBE_ERROR;
+ CMD_PRINT_FMT("Q-PROBE FAILED, IQ = %d mA", drain_current);
+ continue;
+ }
+ }
+ else
+ {
+ CMD_ERROR("ACTIVE GATE PROBE");
+ }
+ }
+
+ else if (CMD_SWITCH(CMD_POWER_SET, cmd_buffer))
+ {
+ if (argc != 1)
+ {
+ CMD_ERROR("USAGE: POWER <cdBm>");
+ continue;
+ }
+
+ int16_t rf_power = argv[0];
+
+ if (rf_power < DRAIN_POWER_LOW_LIM ||
+ rf_power > DRAIN_POWER_HIGH_LIM ||
+ (rf_power % DRAIN_POWER_MODULUS) != 0)
+ {
+ CMD_ERROR("INVALID INPUT POWER");
+ continue;
+ }
+
+ if (!gate_probed)
+ {
+ CMD_PRINT("NO GATE PROBE");
+ continue;
+
+ }
+
+ system_status.p_set = rf_power;
+
+ CMD_PRINT_FMT("POWER SETPOINT = %d cdBm", rf_power);
+ CMD_PRINT("STARTING LINEAR SWEEP");
+ drain_sweep_pwr(rf_power);
+ CMD_PRINT_FMT("SWEEP COMPLETED IN %d ms", system_status.d_time);
+ }
+
+ else if (CMD_SWITCH(CMD_DRAIN_SET, cmd_buffer))
+ {
+ if (argc != 1)
+ {
+ CMD_ERROR("USAGE: DRAIN <count>");
+ continue;
+ }
+
+ uint16_t drain_count = argv[0];
+ if (drain_count > 4096)
+ {
+ CMD_ERROR("RANGE ERROR");
+ continue;
+ }
+
+ dac_write(MCP4725_ID_DRAIN_VOLT, drain_count, 1);
+ }
+
+ else if (CMD_SWITCH(CMD_RX, uart_buffer))
+ {
+ CMD_PRINT("RADIO RX MODE");
+ si4468_rx_mode();
+ }
+
+ else if (CMD_SWITCH(CMD_TX, uart_buffer))
+ {
+ CMD_PRINT("RADIO TX MODE");
+ si4468_tx_mode();
+ }
+
+ else if (CMD_SWITCH(CMD_HELP, uart_buffer))
+ {
+ uint16_t i = 0x0;
+
+ CMD_PRINT("DUMP COMMANDS");
+ printf("- COMMANDS -\n");
+ for(i = 0; i < CMD_SIZE; i++)
+ {
+ printf_P(PSTR("%-10s - %-10s\n"),
+ pgm_read_word(&cmd_lut[i][0]),
+ pgm_read_word(&cmd_lut[i][1]));
+ }
+ }
+
+ else if (CMD_SWITCH(CMD_LINK_REPLY, uart_buffer))
+ {
+ CMD_PRINT("HELLO");
+ }
+
+ else if (CMD_SWITCH(CMD_RESET, uart_buffer))
+ {
+ CMD_PRINT("SOFT RESET");
+ _delay_ms(10);
+
+ bsp_soft_reset();
+ }
+
+ else
+ {
+ CMD_PRINT("UNKNOWN COMMAND");
+ }
+ }
+ }
+}
+
+int main()
+{
+ setup();
+ system_info();
+
+ loop();
+
+ return 0;
+}
+
+
diff --git a/firmware/src/module/drain.c b/firmware/src/module/drain.c new file mode 100644 index 0000000..1cb6110 --- /dev/null +++ b/firmware/src/module/drain.c @@ -0,0 +1,123 @@ +/** + * + * Author: Dylan Muller + * Copyright (c) 2025 + * All rights reserved. + * + * - Commercial/IP use prohibited. + * - Attribution required. + * See License.txt + * + */ + +#include "setup.h" + +#include "peripheral/timer.h" + +#include "driver/mcp3202.h" +#include "driver/mcp4725.h" +#include "driver/si4468.h" + +#include "module/gate.h" +#include "module/drain.h" + +#include "util.h" +#include "status.h" + +#include <stdlib.h> +#include <stdio.h> +#include <avr/interrupt.h> +#include <util/delay.h> + +extern t_drain_status drain_status; +extern t_system_status system_status; + +uint16_t drain_sweep_pwr( + int16_t target_fw_pwr +) +{ + uint16_t drain_count = 0x0; + uint16_t drain_inc = 0x0; + uint16_t fw_pwr_adc = 0x0; + int16_t fw_pwr = 0x0; + uint16_t test_count = 0x0; + int16_t test_boundary = DRAIN_TEST_BOUNDARY; + + system_status.status = SYSTEM_STATUS_BUSY; + drain_status.status = DRAIN_STATUS_POWER_CONTROL; + + drain_count = dac_read(MCP4725_ID_DRAIN_VOLT, 1); + _delay_ms(TRANSACT_DELAY_MS); + + si4468_tx_mode(); + _delay_ms(TRANSACT_DELAY_MS); + + dac_write(MCP4725_ID_DRAIN_VOLT, drain_count, 1); + _delay_ms(TRANSACT_DELAY_MS); + + fw_pwr_adc = adc_read_n(MCP3202_ID_FW_POWER, 10); + util_count_to_pwr(fw_pwr_adc, &fw_pwr); + + _delay_ms(TRANSACT_DELAY_MS); + + timer_reset(); + uint32_t time_start = timer_millis(); + bool timeout = false; + + while ((test_count < DRAIN_TEST_COUNT) && + (drain_count < DRAIN_PROBE_LIMIT)) + { + if ((timer_millis() - time_start) > DRAIN_SETPOINT_TIMEOUT_MS) + { + timeout = true; + break; + } + + if (abs(fw_pwr - target_fw_pwr) > DRAIN_PROBE_INC_THRESHOLD) + { + drain_inc = DRAIN_PROBE_INC_COARSE; + } + else + { + drain_inc = DRAIN_PROBE_INC_FINE; + } + + if (fw_pwr < (target_fw_pwr)) + { + drain_count += drain_inc; + } + else if (fw_pwr > (target_fw_pwr)) + { + drain_count -= drain_inc; + } + + dac_write(MCP4725_ID_DRAIN_VOLT, drain_count, 1); + _delay_us(DRAIN_LOOP_DELAY_US); + + fw_pwr_adc = adc_read_n(MCP3202_ID_FW_POWER, DRAIN_POWER_SAMPLES); + util_count_to_pwr(fw_pwr_adc, &fw_pwr); + + if (fw_pwr <= (target_fw_pwr + test_boundary) && + fw_pwr >= (target_fw_pwr - test_boundary)) + { + test_count += 1; + } + } + + system_status.d_time = (uint16_t)(timer_millis() - time_start); + + if (timeout) + { + system_status.status = SYSTEM_STATUS_SETPOINT_TIMEOUT; + } + else if(test_count >= DRAIN_TEST_COUNT) + { + system_status.status = SYSTEM_STATUS_SETPOINT_REACHED; + } + else + { + system_status.status = SYSTEM_STATUS_SETPOINT_FAIL; + } + + return test_count; +} diff --git a/firmware/src/module/gate.c b/firmware/src/module/gate.c new file mode 100644 index 0000000..b143eab --- /dev/null +++ b/firmware/src/module/gate.c @@ -0,0 +1,78 @@ +/** + * + * Author: Dylan Muller + * Copyright (c) 2025 + * All rights reserved. + * + * - Commercial/IP use prohibited. + * - Attribution required. + * See License.txt + * + */ + +#include "setup.h" + +#include "driver/mcp3202.h" +#include "driver/mcp4725.h" + +#include "module/gate.h" + +#include "util.h" +#include "status.h" + +#include <avr/interrupt.h> +#include <util/delay.h> + +extern t_gate_status gate_status; +extern t_system_status system_status; + +uint16_t gate_probe( + uint16_t target_amp, + uint16_t* probe_result +) +{ + uint16_t probe_volt = 0x0; + uint16_t drain_amp = 0x0; + uint16_t gate_count = 0x0; + uint16_t drain_count = 0x0; + + system_status.status = SYSTEM_STATUS_BUSY; + + util_volt_to_count(GATE_PROBE_DRAIN, &drain_count); + util_volt_to_count(GATE_PROBE_START, &gate_count ); + + dac_write(MCP4725_ID_GATE_VOLT, gate_count, 0); + _delay_ms(TRANSACT_DELAY_MS); + dac_write(MCP4725_ID_DRAIN_VOLT, drain_count, 0); + _delay_ms(TRANSACT_DELAY_MS); + + while((drain_amp < target_amp) && probe_volt < GATE_PROBE_LIMIT) + { + gate_count += GATE_PROBE_INC; + dac_write(MCP4725_ID_GATE_VOLT, gate_count, 0); + _delay_us(GATE_LOOP_DELAY_US); + + drain_count = adc_read(MCP3202_ID_DRAIN_AMP, 0); + util_count_to_volt(drain_count, &drain_amp); + util_count_to_volt(gate_count, &probe_volt); + } + + _delay_ms(TRANSACT_DELAY_MS); + drain_count = adc_read(MCP3202_ID_DRAIN_AMP, 0); + util_count_to_volt(drain_count, &drain_amp); + + if(GATE_PA_POWER_DOWN) + { + _delay_ms(TRANSACT_DELAY_MS); + dac_write(MCP4725_ID_DRAIN_VOLT, 0, 0); + } + + gate_status.q_amp = drain_amp; + gate_status.q_volt = probe_volt; + + *probe_result = probe_volt; + + system_status.status = SYSTEM_STATUS_IDLE; + + return drain_amp; +} diff --git a/firmware/src/peripheral/ring.c b/firmware/src/peripheral/ring.c new file mode 100644 index 0000000..eacb654 --- /dev/null +++ b/firmware/src/peripheral/ring.c @@ -0,0 +1,115 @@ +/** + * + * Author: Dylan Muller + * Copyright (c) 2025 + * All rights reserved. + * + * - Commercial/IP use prohibited. + * - Attribution required. + * See License.txt + * + */ + +#include "peripheral/ring.h" + +#define RING_INC_ROLL_OVER(n, s, e) (((n)+1>=(e)) ? (s) : (n)+1) + +ring_t ring_init( + uint8_t *buf, + size_t len +) +{ + return RING_INIT(buf, len); +} + +bool ring_is_empty( + ring_t ring +) +{ + return ring.read == ring.write; +} + +bool ring_is_full( + ring_t ring +) +{ + return RING_INC_ROLL_OVER(ring.write, ring.buf, ring.end) == ring.read; +} + +size_t ring_push_available( + ring_t ring +) +{ + if(ring.write < ring.read) + return ring.read - ring.write - 1; + else + return (ring.end - ring.buf) - (ring.write - ring.read) - 1; +} + +size_t ring_pop_available( + ring_t ring +) +{ + if(ring.read <= ring.write) + return ring.write - ring.read; + else + return (ring.end - ring.buf) - (ring.read - ring.write); +} + +bool ring_push( + ring_t *ring, + uint8_t data +) +{ + if(ring_is_full(*ring)) + return 1; + + *ring->write = data; + ring->write = RING_INC_ROLL_OVER(ring->write, ring->buf, ring->end); + + return 0; +} + +bool ring_push_over( + ring_t *ring, + uint8_t data +) +{ + *ring->write = data; + ring->write = RING_INC_ROLL_OVER(ring->write, ring->buf, ring->end); + + if(ring->read == ring->write) + { + ring->read = RING_INC_ROLL_OVER(ring->read, ring->buf, ring->end); + return 1; + } + + return 0; +} + +bool ring_pop( + ring_t *ring, + uint8_t *data +) +{ + if(ring_is_empty(*ring)) + return 1; + + *data = *ring->read; + ring->read = RING_INC_ROLL_OVER(ring->read, ring->buf, ring->end); + + return 0; +} + +bool ring_peek( + ring_t *ring, + uint8_t *data +) +{ + if(ring_is_empty(*ring)) + return 1; + + *data = *ring->read; + + return 0; +} diff --git a/firmware/src/peripheral/spi.c b/firmware/src/peripheral/spi.c new file mode 100644 index 0000000..884985d --- /dev/null +++ b/firmware/src/peripheral/spi.c @@ -0,0 +1,106 @@ +/** + * + * Author: Dylan Muller + * Copyright (c) 2025 + * All rights reserved. + * + * - Commercial/IP use prohibited. + * - Attribution required. + * See License.txt + * + */ + +#include "setup.h" + +#include "peripheral/spi.h" + +#include <stdio.h> +#include <avr/io.h> +#include <avr/interrupt.h> +#include <util/delay.h> + +#if SPI_MODE == 0 + #define CPOL_VALUE 0 + #define CPHA_VALUE 0 +#elif SPI_MODE == 1 + #define CPOL_VALUE 0 + #define CPHA_VALUE 1 +#elif SPI_MODE == 2 + #define CPOL_VALUE 1 + #define CPHA_VALUE 0 +#elif SPI_MODE == 3 + #define CPOL_VALUE 1 + #define CPHA_VALUE 1 +#else + #error "No valid SPI_MODE defined!" +#endif + +#if SPI_DORD == 0 + #define DORD_VALUE 0 +#elif SPI_DORD == 1 + #define DORD_VALUE 1 +#else + #error "No valid SPI_DORD defined!" +#endif + +static volatile uint8_t *spi_out; +static volatile uint8_t *spi_in; +static volatile size_t spi_len; +static volatile uint8_t *spi_port; +static volatile uint8_t spi_pin; + +void spi_init(void) +{ + DDRB |= (1 << DDB2) | (1 << DDB3) | (1 << DDB5); + + SPSR |= (SPI2X_VALUE << SPI2X); + SPCR |= (1 << SPIE) | (1 << SPE) | (DORD_VALUE << DORD) | (1 << MSTR) + | (CPOL_VALUE << CPOL) | (CPHA_VALUE << CPHA) + | (SPR1_VALUE << SPR1) | (SPR0_VALUE << SPR0); +} + +bool spi_busy(void) +{ + return spi_len; +} + +void spi_flush(void) +{ + while(spi_len); +} + +void spi_start( + uint8_t *out, + uint8_t *in, + size_t len, + uint8_t *port, + uint8_t pin +) +{ + spi_flush(); + + spi_out = out; + spi_in = in; + spi_len = len; + spi_port = port; + spi_pin = pin; + + if(spi_port) + *spi_port &= ~(1 << spi_pin); + + SPDR = *spi_out++; +} + +ISR(SPI_STC_vect) +{ + if(spi_in) + { + *spi_in++ = SPDR; + } + + if(--spi_len) + SPDR = *spi_out++; + else + if(spi_port) + *spi_port |= (1 << spi_pin); +} diff --git a/firmware/src/peripheral/timer.c b/firmware/src/peripheral/timer.c new file mode 100644 index 0000000..1caff1c --- /dev/null +++ b/firmware/src/peripheral/timer.c @@ -0,0 +1,57 @@ +/** + * + * Author: Dylan Muller + * Copyright (c) 2025 + * All rights reserved. + * + * - Commercial/IP use prohibited. + * - Attribution required. + * See License.txt + * + */ + +#include "setup.h" + +#include "peripheral/timer.h" + +#include <stdint.h> +#include <avr/io.h> +#include <avr/interrupt.h> +#include <util/atomic.h> + +uint32_t millis_count = 0; + +void timer_init(void) +{ + uint32_t ctc_overflow; + + ctc_overflow = ((F_CPU / 1000) / 8); + TCCR1B |= (1 << WGM12) | (1 << CS11); + + OCR1AH = (ctc_overflow >> 8); + OCR1AL = ctc_overflow; + + TIMSK1 |= (1 << OCIE1A); +} + +void timer_reset(void) +{ + ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { + millis_count = 0; + } +} + +uint32_t timer_millis(void) +{ + uint32_t millis; + + ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { + millis = millis_count; + } + return millis; +} + +ISR(TIMER1_COMPA_vect) +{ + millis_count++; +} diff --git a/firmware/src/peripheral/twi.c b/firmware/src/peripheral/twi.c new file mode 100644 index 0000000..671490b --- /dev/null +++ b/firmware/src/peripheral/twi.c @@ -0,0 +1,114 @@ +/** + * + * Author: Dylan Muller + * Copyright (c) 2025 + * All rights reserved. + * + * - Commercial/IP use prohibited. + * - Attribution required. + * See License.txt + * + */ + +#include "setup.h" + +#include "peripheral/twi.h" + +#include <avr/io.h> +#include <avr/interrupt.h> +#include <util/delay.h> +#include <util/twi.h> + +#define TWBR_VALUE ((F_CPU/TWI_FREQUENCY - 16) / (2 * TWI_PRESCALER)) + +static uint8_t twi_address; +static uint8_t* twi_data; +static size_t twi_index; +static size_t twi_len; + +void twi_init(void) +{ + TWBR = TWBR_VALUE; + TWSR = (TWPS1_VALUE << TWPS1) | (TWPS0_VALUE << TWPS0); + + TWCR = (1 << TWINT) | (1 << TWEN); +} + +bool twi_busy(void) +{ + return TWCR & (1<<TWIE); +} + +void twi_flush(void) +{ + while(TWCR & (1<<TWIE)); +} + +void twi_start( + uint8_t address, + uint8_t *data, + size_t len +) +{ + twi_flush(); + + twi_address = address; + twi_data = data; + twi_len = len; + + TWCR = (1 << TWINT) | (1 << TWSTA) | (1 << TWEN) | (1 << TWIE); +} + +ISR(TWI_vect) +{ + switch(TW_STATUS) + { + case TW_START: + case TW_REP_START: + twi_index = 0; + TWDR = twi_address; + TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWIE); + break; + + case TW_MT_SLA_ACK: + case TW_MT_DATA_ACK: + if(twi_index < twi_len) + { + TWDR = twi_data[twi_index++]; + TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWIE); + } + else + { + TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWSTO); + } + break; + + case TW_MR_DATA_ACK: + twi_data[twi_index++] = TWDR; + case TW_MR_SLA_ACK: + if(twi_index < twi_len-1) + { + TWCR = (1 << TWINT) | (1 << TWEA) | (1 << TWEN) | (1 << TWIE); + } + else + { + TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWIE); + } + break; + + case TW_MR_DATA_NACK: + twi_data[twi_index++] = TWDR; + TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWSTO); + break; + + case TW_MT_ARB_LOST: + TWCR = (1 << TWINT) | (1 << TWSTA) | (1 << TWEN) | (1 << TWIE); + break; + + case TW_MT_SLA_NACK: + case TW_MT_DATA_NACK: + case TW_MR_SLA_NACK: + default: + TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWSTO); + } +} diff --git a/firmware/src/peripheral/uart.c b/firmware/src/peripheral/uart.c new file mode 100644 index 0000000..defcf54 --- /dev/null +++ b/firmware/src/peripheral/uart.c @@ -0,0 +1,239 @@ +/** + * + * Author: Dylan Muller + * Copyright (c) 2025 + * All rights reserved. + * + * - Commercial/IP use prohibited. + * - Attribution required. + * See License.txt + * + */ + +#include "setup.h" + +#include "peripheral/ring.h" +#include "peripheral/uart.h" + +#include "status.h" +#include "cmd.h" + +#include <avr/io.h> +#include <avr/interrupt.h> +#include <util/atomic.h> +#include <util/setbaud.h> + +extern t_system_status system_status; + +static int uart_putc( + char c, + FILE *stream +) +{ + (void)stream; + + if(uart_tx(c)) + return _FDEV_EOF; + + return c; +} + +static int uart_getc( + FILE *stream +) +{ + uint8_t c; + (void)stream; + + if(uart_rx(&c)) + return _FDEV_EOF; + + return c; +} + +FILE uart_out = FDEV_SETUP_STREAM(uart_putc, NULL, _FDEV_SETUP_WRITE); +FILE uart_in = FDEV_SETUP_STREAM(NULL, uart_getc, _FDEV_SETUP_READ); + +static volatile ring_t uart_tx_ring; +static volatile ring_t uart_rx_ring; + +static volatile uint8_t uart_tx_buf[UART_BUF_SIZE]; +static volatile uint8_t uart_rx_buf[UART_BUF_SIZE]; + +void uart_init(void) +{ + uart_tx_ring = ring_init((uint8_t*)uart_tx_buf, UART_BUF_SIZE - 1); + uart_rx_ring = ring_init((uint8_t*)uart_rx_buf, UART_BUF_SIZE - 1); + + UBRR0H = UBRRH_VALUE; + UBRR0L = UBRRL_VALUE; + UCSR0B |= (1 << RXCIE0) | (1 << RXEN0) | (1 << TXEN0); + UCSR0C = (1 << UCSZ01) | (1 << UCSZ00); + + stdout = &uart_out; + stdin = &uart_in; +} + +bool uart_tx( + uint8_t data +) +{ + bool ret; + + while(ring_is_full(uart_tx_ring)); + + ATOMIC_BLOCK(ATOMIC_RESTORESTATE) + { + ret = ring_push((ring_t*)&uart_tx_ring, data); + } + + if(!ret) + UCSR0B |= (1 << UDRIE0); + + return ret; +} + +bool uart_rx( + uint8_t* data +) +{ + bool ret; + + ATOMIC_BLOCK(ATOMIC_RESTORESTATE) + { + ret = ring_pop((ring_t*)&uart_rx_ring, data); + } + + return ret; +} + +size_t uart_tx_burst( + uint8_t *data, + size_t size +) +{ + size_t i = 0; + + while(i<size && !uart_tx(*data++)) + i++; + + return i; +} + +size_t uart_rx_burst( + uint8_t* data, + size_t len +) +{ + size_t i = 0; + + while(i<len && !uart_rx(data++)) + i++; + + return i; +} + +size_t uart_tx_available(void) +{ + size_t ret; + + ATOMIC_BLOCK(ATOMIC_RESTORESTATE) + { + ret = ring_push_available(uart_tx_ring); + } + + return ret; +} + +size_t uart_rx_available(void) +{ + size_t ret; + + ATOMIC_BLOCK(ATOMIC_RESTORESTATE) + { + ret = ring_pop_available(uart_rx_ring); + } + + return ret; +} + +bool uart_rx_peek( + uint8_t *data +) +{ + bool ret; + + ATOMIC_BLOCK(ATOMIC_RESTORESTATE) + { + ret = ring_peek((ring_t*)&uart_rx_ring, data); + } + + return ret; +} + +void uart_tx_flush(void) +{ + bool empty; + do + { + ATOMIC_BLOCK(ATOMIC_RESTORESTATE) + { + empty = ring_is_empty(uart_tx_ring); + } + } while(!empty); +} + +char *uart_ngets(char *s, size_t n) +{ + uint8_t c; + static size_t i = 0; + + + while(!uart_rx(&c)) + { + s[i++] = c; + + if(c == '\n' || i >= n-1) + { + s[i] = '\0'; + i = 0; + + return s; + } + } + + return NULL; +} + +ISR(USART_UDRE_vect) +{ + uint8_t c; + + if(!ring_pop((ring_t*)&uart_tx_ring, &c)) + UDR0 = c; + + else + UCSR0B &= ~(1 << UDRIE0); +} + +ISR(USART_RX_vect) +{ + if (system_status.status == SYSTEM_STATUS_BUSY) + { + // system busy.. lock now! + CMD_ERROR("SYSTEM BUSY"); + system_status.status = SYSTEM_STATUS_LOCKED; + } + + if (system_status.status != SYSTEM_STATUS_LOCKED) + { + #ifdef UART_OVERWRITE + ring_push_over((ring_t*)&uart_rx_ring, UDR0); + #else + ring_push((ring_t*)&uart_rx_ring, UDR0); + #endif + } + else{ + (uint8_t)UDR0; + } +} diff --git a/firmware/src/status.c b/firmware/src/status.c new file mode 100644 index 0000000..d3bb9eb --- /dev/null +++ b/firmware/src/status.c @@ -0,0 +1,46 @@ +/** + * + * Author: Dylan Muller + * Copyright (c) 2025 + * All rights reserved. + * + * - Commercial/IP use prohibited. + * - Attribution required. + * See License.txt + * + */ + +#include "status.h" +#include <avr/pgmspace.h> + +t_gate_status gate_status; +t_drain_status drain_status; +t_system_status system_status; + +const char* const gate_lut[] PROGMEM = +{ + "INACTIVE", + "PROBE_ERR", + "PROBE_OK", + "PROBE_TIME" +}; + +const char* const drain_lut[] PROGMEM = +{ + "INACTIVE", + "POWER_SET", + "OVERRIDE", + "ADC_ERROR", + "AMP_ALARM" +}; + +const char* const system_lut[] PROGMEM = +{ + "IDLE", + "BUSY", + "LOCKED", + "SET_FAIL", + "SET_REACHED", + "SET_TIME", + "VSWR_ALARM" +}; diff --git a/firmware/src/util.c b/firmware/src/util.c new file mode 100644 index 0000000..af6ffed --- /dev/null +++ b/firmware/src/util.c @@ -0,0 +1,152 @@ +/** + * + * Author: Dylan Muller + * Copyright (c) 2025 + * All rights reserved. + * + * - Commercial/IP use prohibited. + * - Attribution required. + * See License.txt + * + */ + +#include "util.h" + +#include <stdio.h> +#include <avr/pgmspace.h> + +extern int __heap_start, *__brkval; + +const uint16_t fw_pwr_gradient[] = { 249, 356, 374, 388, 400, 402, 435, 460, 500, 553 }; +const int16_t fw_pwr_intercept[] = { -5418, -3810, -3602, -3431, -3289, -3261, -2877, -2601, -2189, -1725 }; +const uint16_t fw_pwr_threshold[] = { 1288, 1548, 1704, 1812, 1897, 1967, 2164, 2301, 2411, 2505 }; + +uint8_t util_volt_to_count( + uint16_t volt, + uint16_t* count +) +{ + uint8_t bits = 0x0; + uint32_t x = 0x0; + uint32_t y = 0x0; + uint16_t i = 0x0; + + bits = UTIL_CONV_BITS; + + if (volt > UTIL_SYSTEM_VOLT) + { + return 1; + } + + for (i = 0; i < bits; i++) + { + x |= UTIL_CONV_BIT(i); + } + + y = ((uint32_t)volt) * x; + y /= UTIL_SYSTEM_VOLT; + + *count = (uint16_t)y; + return 0; +} + +uint8_t util_count_to_volt( + uint16_t count, + uint16_t* volt +) +{ + uint8_t bits = 0x0; + uint32_t x = 0x0; + uint32_t y = 0x0; + uint16_t i = 0x0; + + bits = UTIL_CONV_BITS; + + for (i = 0; i < bits; i++) + { + x |= UTIL_CONV_BIT(i); + } + + if (count > x) + { + return 1; + } + + y = ((uint32_t)count) * UTIL_SYSTEM_VOLT; + y /= x; + + *volt = (uint16_t)y; + return 0; +} + +int8_t util_count_to_pwr( + uint16_t count, + int16_t* cpwr +) +{ + uint32_t x = 0x0; + int16_t y = 0x0; + uint16_t slope = 0x0; + int16_t intercept = 0x0; + uint16_t i = 0; + + uint8_t pwr_cal_size = sizeof(fw_pwr_gradient) / sizeof(uint16_t); + uint8_t pwr_last_element = pwr_cal_size - 1; + + if(count >= fw_pwr_threshold[pwr_last_element]) + { + slope = fw_pwr_gradient[pwr_last_element]; + intercept = fw_pwr_intercept[pwr_last_element]; + } + else if (count <= fw_pwr_threshold[0]) + { + slope = fw_pwr_gradient[0]; + intercept = fw_pwr_intercept[0]; + } + else + { + for(i = 0; i < pwr_cal_size; i++) + { + if(count < fw_pwr_threshold[i]) + { + slope = fw_pwr_gradient[i]; + intercept = fw_pwr_intercept[i]; + break; + } + } + } + + x = (((uint32_t)count * 1000) / slope); + y = (int16_t)x; + + y = y + intercept; + *cpwr = y; + + return 0; +} + +void util_print_pwr( + int16_t cpwr +) +{ + int16_t integer_part = cpwr / 100; + + int16_t fractional_part = cpwr % 100; + + if (fractional_part < 0) { + fractional_part = -fractional_part; + } + + printf("%d.%02d dBm\n", integer_part, fractional_part); +} + +uint16_t util_get_free_mem(void) +{ + uint16_t free_mem; + if ((int)__brkval == 0) { + free_mem = (int)&free_mem - (int)&__heap_start; + } else { + free_mem = (int)&free_mem - (int)__brkval; + } + return free_mem; +} |
