diff --git a/cw/ax25.c b/cw/ax25.c deleted file mode 100644 index 15b127c2..00000000 --- a/cw/ax25.c +++ /dev/null @@ -1,94 +0,0 @@ -/* - * A sample application transmitting AFSK at 1200 baud - * - * Portions Copyright (C) 2018 Libre Space Foundation - * Portions Copyright (C) 2018 Jonathan Brandenburg - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "ax25.h" -#include -#include "ax5043.h" -#include "status.h" - -static uint8_t __tx_buffer[MAX_FRAME_LEN]; - -/** - * Creates the header field of the AX.25 frame - * @param conf the AX.25 handle - * @param dest_addr the destination callsign address - * @param dest_ssid the destination SSID - * @param src_addr the callsign of the source - * @param src_ssid the source SSID - * @param preamble_len the number of the AX.25 repetitions in the preamble - * @param postamble_len the number of the AX.25 repetitions in the postamble - */ -int ax25_init(ax25_conf_t *conf, const uint8_t *dest_addr, uint8_t dest_ssid, - const uint8_t *src_addr, uint8_t src_ssid, uint8_t preamble_len, - uint8_t postamble_len) { - uint16_t i = 0; - - if (!conf || !dest_addr || !src_addr || preamble_len < 4 - || !postamble_len) { - return -PQWS_INVALID_PARAM; - } - - conf->preamble_len = preamble_len; - conf->postable_len = postamble_len; - uint8_t *out = conf->addr_field; - - for (i = 0; i < strnlen((char *) dest_addr, AX25_CALLSIGN_MAX_LEN); i++) { - *out++ = (uint8_t) (dest_addr[i] << 1); - } - /* - * Perhaps the destination callsign was smaller that the maximum allowed. - * In this case the leftover bytes should be filled with space - */ - for (; i < AX25_CALLSIGN_MAX_LEN; i++) { - *out++ = ' ' << 1; - } - /* Apply SSID, reserved and C bit */ - /* FIXME: C bit is set to 0 implicitly */ - *out++ = (uint8_t) ((0x0F & dest_ssid) << 1) | 0x60; - //*out++ = ((0b1111 & dest_ssid) << 1) | 0b01100000; - - for (i = 0; i < strnlen((char *) src_addr, AX25_CALLSIGN_MAX_LEN); i++) { - *out++ = (uint8_t) (src_addr[i] << 1); - } - for (; i < AX25_CALLSIGN_MAX_LEN; i++) { - *out++ = ' ' << 1; - } - /* Apply SSID, reserved and C bit. As this is the last address field - * the trailing bit is set to 1. - */ - /* FIXME: C bit is set to 0 implicitly */ - *out++ = (uint8_t) ((0x0F & src_ssid) << 1) | 0x61; - //*out++ = ((0b1111 & src_ssid) << 1) | 0b01100001; - conf->addr_field_len = AX25_MIN_ADDR_LEN; - return PQWS_SUCCESS; -} - -int ax25_tx_frame(ax25_conf_t *hax25, ax5043_conf_t *hax, - const uint8_t *payload, uint32_t len) { - if (!hax25 || !hax || !payload || !len) { - return -PQWS_INVALID_PARAM; - } - - memcpy(__tx_buffer, hax25->addr_field, hax25->addr_field_len); - memcpy(__tx_buffer + hax25->addr_field_len, payload, len); - - return ax5043_tx_frame(hax, __tx_buffer, len + hax25->addr_field_len, - hax25->preamble_len, hax25->postable_len, 1000); -} diff --git a/cw/ax25.h b/cw/ax25.h deleted file mode 100644 index 2784c93d..00000000 --- a/cw/ax25.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * A sample application transmitting AFSK at 1200 baud - * - * Portions Copyright (C) 2018 Libre Space Foundation - * Portions Copyright (C) 2018 Jonathan Brandenburg - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef AX25_H_ -#define AX25_H_ - -#include -#include "ax5043.h" - -#define AX25_MAX_ADDR_LEN 28 -#define AX25_MAX_FRAME_LEN 256 -#define AX25_MIN_ADDR_LEN 14 -#define AX25_SYNC_FLAG 0x7E -#define AX25_MIN_CTRL_LEN 1 -#define AX25_MAX_CTRL_LEN 2 -#define AX25_CALLSIGN_MAX_LEN 6 -#define AX25_CALLSIGN_MIN_LEN 2 -#define AX25_PREAMBLE_LEN 16 -#define AX25_POSTAMBLE_LEN 16 - -/** - * AX.25 Frame types - */ -typedef enum { - AX25_I_FRAME, //!< AX25_I_FRAME Information frame - AX25_S_FRAME, //!< AX25_S_FRAME Supervisory frame - AX25_U_FRAME, //!< AX25_U_FRAME Unnumbered frame - AX25_UI_FRAME /**!< AX25_UI_FRAME Unnumbered information frame */ -} ax25_frame_type_t; - -typedef struct { - uint8_t preamble_len; - uint8_t postable_len; - uint8_t addr_field[AX25_MAX_ADDR_LEN]; - uint32_t addr_field_len; -} ax25_conf_t; - -int -ax25_init(ax25_conf_t *conf, const uint8_t *dest_addr, uint8_t dest_ssid, - const uint8_t *src_addr, uint8_t src_ssid, uint8_t preamble_len, - uint8_t postamble_len); -int ax25_tx_frame(ax25_conf_t *hax25, ax5043_conf_t *hax, - const uint8_t *payload, uint32_t len); - -#endif /* AX25_H_ */ diff --git a/cw/ax5043.c b/cw/ax5043.c deleted file mode 100644 index a6763050..00000000 --- a/cw/ax5043.c +++ /dev/null @@ -1,1126 +0,0 @@ -/* - * A sample application transmitting AFSK 1200 baud - * - * Portions Copyright (C) 2018 Libre Space Foundation - * Portions Copyright (C) 2018 Jonathan Brandenburg - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include -#include -#include -#include "ax25.h" -#include "ax5043.h" -#include "status.h" -#include "utils.h" -#include "spi/ax5043spi.h" - -static uint8_t single_fifo_access = 0; - -static uint8_t __tx_buf[MAX_FRAME_LEN]; -static size_t __tx_buf_idx = 0; -static uint8_t __tx_fifo_chunk[AX5043_FIFO_MAX_SIZE]; -static uint32_t __tx_remaining = 0; - -/** - * FIFO command for the preamble. The third byte corresponds the length of - * the preamble and is set by the TX routine for every frame - */ -static uint8_t __preamble_cmd[4] = { AX5043_FIFO_REPEATDATA_CMD, -AX5043_FIFO_PKTSTART | AX5043_FIFO_RAW | AX5043_FIFO_NOCRC, 0, -AX25_SYNC_FLAG }; - -/** - * FIFO command for the postable. The third byte corresponds the length of - * the postable and is set by the TX routine for every frame - */ -static uint8_t __postamble_cmd[4] = { -AX5043_FIFO_REPEATDATA_CMD, -AX5043_FIFO_PKTSTART | AX5043_FIFO_PKTEND | AX5043_FIFO_RAW | AX5043_FIFO_NOCRC, - 0, AX25_SYNC_FLAG }; - -/** - * Indicates if a TX is currently active - */ -static volatile uint8_t __tx_active = 0; - -static ax5043_conf_t *__ax5043_conf = NULL; - -static inline int set_tx_black_magic_regs(); - -/** - * Checks if the AX5043 handler is valid - * @param conf the AX5043 configuration handler pointer - * @return 1 if it is valid 0 otherwise - */ -static uint8_t is_ax5043_conf_valid(ax5043_conf_t *conf) { - if (!conf || !conf->f_xtal) { - return 0; - } - return 1; -} - -/** - * Resets the AX5043 - * @param conf the AX5043 configuration handler - * @return 0 on success or appropriate negative error code - */ -int ax5043_reset(ax5043_conf_t *conf) { - int ret; - uint8_t val; - - if (!is_ax5043_conf_valid(conf)) { - return -PQWS_INVALID_PARAM; - } - - conf->rf_init = 0; - usleep(100); - - /* Reset the chip using the appropriate register */ - val = BIT(7); - ret = ax5043_spi_write_8(conf, AX5043_REG_PWRMODE, val); - if (ret) { - return ret; - } - usleep(100); - /* Clear the reset bit, but keep REFEN and XOEN */ - ret = ax5043_spi_read_8(conf, &val, AX5043_REG_PWRMODE); - if (ret) { - return ret; - } - val &= (BIT(6) | BIT(5)); - ret = ax5043_spi_write_8(conf, AX5043_REG_PWRMODE, val); - if (ret) { - return ret; - } - usleep(100); - - ret = ax5043_set_power_mode(conf, POWERDOWN); - if (ret) { - return ret; - } - return PQWS_SUCCESS; -} - -/** - * Initialization routine for the AX5043 IC - * @param conf the AX5043 configuration handler - * @param spi the SPI handler - * @param f_xtal the frequency of the crystal or the TCXO - * @param vco the VCO mode - * @return 0 on success or appropriate negative error code - */ -int ax5043_init(ax5043_conf_t *conf, uint32_t f_xtal, vco_mode_t vco) { - int ret; - uint8_t revision; - uint8_t val; - - if (!conf) { - return -PQWS_INVALID_PARAM; - } - - /* Set the initial parameters */ - memset(conf, 0, sizeof(ax5043_conf_t)); - - switch (vco) { - case VCO_INTERNAL: - case VCO_EXTERNAL: - conf->vco = vco; - break; - default: - return -PQWS_INVALID_PARAM; - } - - conf->rf_init = 0; - conf->freqsel = -1; - conf->f_xtal = f_xtal; - if (conf->f_xtal > 24800000) { - conf->f_xtaldiv = 2; - } else { - conf->f_xtaldiv = 1; - } - - ret = ax5043_reset(conf); - if (ret) { - return ret; - } - - /* Try first to read the revision register of the AX5043 */ - ret = ax5043_spi_read_8(conf, &revision, AX5043_REG_REV); - if (ret) { - return ret; - } - - if (revision != AX5043_REV) { - return -PQWS_NO_RF_FOUND; - } - - /* To ensure communication try to write and read the scratch register */ - val = AX5043_SCRATCH_TEST; - ret = ax5043_spi_write_8(conf, AX5043_REG_SCRATCH, val); - if (ret) { - return ret; - } - - val = 0x0; - ret = ax5043_spi_read_8(conf, &val, AX5043_REG_SCRATCH); - if (ret) { - return ret; - } - - if (val != AX5043_SCRATCH_TEST) { - return -PQWS_NO_RF_FOUND; - } - - ret = ax5043_set_pll_params(conf); - if (ret) { - return ret; - } - - /* Write the performance register F35 based on the XTAL frequency */ - if (conf->f_xtaldiv == 1) { - ret = ax5043_spi_write_8(conf, 0xF35, 0x10); - } else { - ret = ax5043_spi_write_8(conf, 0xF35, 0x11); - } - if (ret) { - return ret; - } - - /* FIFO maximum chunk */ - ret = ax5043_spi_write_8(conf, AX5043_REG_PKTCHUNKSIZE, - AX5043_PKTCHUNKSIZE_240); - if (ret) { - return ret; - } - - /* Set RF parameters */ - ret = ax5043_freqsel(conf, FREQA_MODE); - if (ret) { - return ret; - } - - /* - * We use APRS for all transmitted frames. APRS is encapsulated in a - * AX.25 frame. For 9600 baudrate is FSK9600 G3RUH compatible modem - */ - ret = ax5043_aprs_framing_setup(conf); - if (ret) { - return ret; - } - - /* Setup TX only related parameters */ - ret = ax5043_conf_tx_path(conf); - if (ret) { - return ret; - } - - /* Set an internal copy for the ax5042_wait_for_transmit function */ - __ax5043_conf = conf; - - if (ret) { - return ret; - } - ax5043_enable_pwramp(conf, AX5043_EXT_PA_DISABLE); - return PQWS_SUCCESS; -} - -/** - * Performs TX specific configuration of the AX5043 - * @param conf the AX5043 configuration handler - * @return 0 on success or appropriate negative error code - */ -int ax5043_conf_tx_path(ax5043_conf_t *conf) { - int ret; - - ret = ax5043_set_tx_synth(conf); - if (ret) { - return ret; - } - - ret = ax5043_set_tx_baud(conf, TX_BAUDRATE); - if (ret) { - return ret; - } - - ret = ax5043_set_tx_freq(conf, TX_FREQ_HZ); - if (ret) { - return ret; - } - - /* Our TX is on single ended mode */ - //ret = ax5043_spi_write_8(conf, AX5043_REG_MODCFGA, - //AX5043_TX_SINGLE_ENDED); - //if (ret) { - // return ret; - //} - - /* Our TX is on double ended mode */ - ret = ax5043_spi_write_8(conf, AX5043_REG_MODCFGA, - AX5043_TX_DIFFERENTIAL); - if (ret) { - return ret; - } - - /* Set the rest of the performance registers for TX */ - ret = set_tx_black_magic_regs(conf); - if (ret) { - return ret; - } - - /* - * As our board has an external PA, reduce the output power to reduce - * the excess bandwidth emissions - */ - //ret = ax5043_spi_write_16(conf, AX5043_REG_TXPWRCOEFFB1, 0x01FF); - //if (ret) { - //return ret; - //} - - // Not using a PA, transmit half power - ret = ax5043_spi_write_16(conf, AX5043_REG_TXPWRCOEFFB1, 0x07FF); - if (ret) { - return ret; - } - - return PQWS_SUCCESS; -} - -/** - * Sets the power mode of the AX5043 - * @param conf the AX5043 configuration handler - * @param mode the power mode - * @return 0 on success or appropriate negative error code - */ -int ax5043_set_power_mode(ax5043_conf_t *conf, power_mode_t mode) { - int ret; - uint8_t val; - - if (!is_ax5043_conf_valid(conf)) { - return -PQWS_INVALID_PARAM; - } - - /* Read the contents of the register */ - ret = ax5043_spi_read_8(conf, &val, AX5043_REG_PWRMODE); - if (ret) { - return ret; - } - - /* Keep REFEN and XOEN values */ - val &= (BIT(6) | BIT(5)); - - switch (mode) { - case POWERDOWN: - val |= AX5043_POWERDOWN; - break; - case DEEPSLEEP: - val |= AX5043_DEEPSLEEP; - break; - case STANDBY: - val |= AX5043_STANDBY; - break; - case FIFO_ENABLED: - val |= AX5043_FIFO_ENABLED; - break; - case RECEIVE_MODE: - val |= AX5043_RECEIVE_MODE; - break; - case RECEIVER_RUNNING: - val |= AX5043_RECEIVER_RUNNING; - break; - case RECEIVER_WOR: - val |= AX5043_RECEIVER_WOR; - break; - case TRANSMIT_MODE: - val |= AX5043_TRANSMIT_MODE; - break; - case FULLTX: - val |= AX5043_FULLTX; - break; - default: - return -PQWS_INVALID_PARAM; - } - return ax5043_spi_write_8(conf, AX5043_REG_PWRMODE, val); -} - -/** - * Sets the RF frequency of the TX. If the previous TX frequency is - * further enough than the new one, this function performs automatically - * auto-ranging. - * - * @param conf the AX5043 configuration handler - * @param freq the target RF frequency - * @return 0 on success or appropriate negative error code - */ -int ax5043_set_tx_freq(ax5043_conf_t *conf, uint32_t freq) { - int ret; - uint32_t prev_freq; - uint32_t reg_val; - uint8_t rfdiv = 0; - uint8_t pllcodediv = 0; - - if (!is_ax5043_conf_valid(conf)) { - return -PQWS_INVALID_PARAM; - } - - /* Check the frequency range. The actual range depends on the VCO used */ - switch (conf->vco) { - case VCO_INTERNAL: - if (freq >= MIN_RF_FREQ_INT_VCO_RFDIV0 - && freq <= MAX_RF_FREQ_INT_VCO_RFDIV0) { - rfdiv = AX5043_RFDIV0; - } else if (freq >= MIN_RF_FREQ_INT_VCO_RFDIV1 - && freq <= MAX_RF_FREQ_INT_VCO_RFDIV1) { - rfdiv = AX5043_RFDIV1; - } else { - return -PQWS_INVALID_PARAM; - } - break; - case VCO_EXTERNAL: - fprintf(stderr, "ERROR: Unexpected use of external VCO\n"); - if (freq >= MIN_RF_FREQ_EXT_VCO_RFDIV0 - && freq <= MAX_RF_FREQ_EXT_VCO_RFDIV0) { - rfdiv = AX5043_RFDIV0; - } else if (freq >= MIN_RF_FREQ_EXT_VCO_RFDIV1 - && freq <= MAX_RF_FREQ_EXT_VCO_RFDIV1) { - rfdiv = AX5043_RFDIV1; - } else { - return -PQWS_INVALID_PARAM; - } - break; - default: - return -PQWS_INVALID_PARAM; - } - prev_freq = conf->tx_freq; - pllcodediv = rfdiv | (uint8_t) (conf->vco << 4); - - // Added by Jonathan Brandenburg - // Have an external inductor - pllcodediv |= BIT(5); - - ret = ax5043_spi_write_8(conf, AX5043_REG_PLLVCODIV, pllcodediv); - if (ret) { - return ret; - } - - /* Write properly the F34 performance register based on the RFDIV*/ - if (rfdiv == AX5043_RFDIV1) { - ret = ax5043_spi_write_8(conf, 0xF34, 0x28); - } else { - ret = ax5043_spi_write_8(conf, 0xF34, 0x08); - } - if (ret) { - return ret; - } - - /* - * Set the RF frequency - * Frequency should be avoided to be a multiple integer of the crystal - * frequency, so we always set to 1 the LSB - */ - reg_val = ((uint32_t) (((float) freq / (float) conf->f_xtal) * (1 << 24)) - | 0x1); - if (conf->freqsel == FREQA_MODE) { - ret = ax5043_spi_write_32(conf, AX5043_REG_FREQA3, reg_val); - } else { - ret = ax5043_spi_write_32(conf, AX5043_REG_FREQB3, reg_val); - } - if (ret) { - return ret; - } - - /* Considered that the frequency successfully changed */ - conf->tx_freq = freq; - - /* If the frequency difference is great enough perform autoranging */ - if (freq + 25000000 > prev_freq || freq - 25000000 < prev_freq) { - ax5043_autoranging(conf); - } - - return PQWS_SUCCESS; -} - -/** - * Set the TX baudrate - * @param conf the AX5043 configuration handler - * @param baud the baudrate - * @return 0 on success or negative error code - */ -int ax5043_set_tx_baud(ax5043_conf_t *conf, uint32_t baud) { - int ret = PQWS_SUCCESS; - uint32_t val; - if (!is_ax5043_conf_valid(conf)) { - return -PQWS_INVALID_PARAM; - } - - val = (uint32_t) ((((float) baud) / (float) conf->f_xtal) * (1 << 24)) - | 0x1; - ret = ax5043_spi_write_24(conf, AX5043_REG_TXRATE2, val); - if (ret) { - return ret; - } - - conf->tx_baudrate = baud; - - /* Set the deviation to standard 3 KHz for FM */ - // For AFSK, FSKDEV = 0.858785 * fDeviation / fXTAL * 2^24 - // - val = (uint32_t) ((0.858785 * 3000.0f / (float) conf->f_xtal) * (1 << 24)) - | 0x1; - ret = ax5043_spi_write_24(conf, AX5043_REG_FSKDEV2, val); - if (ret) { - return ret; - } - - return PQWS_SUCCESS; -} - -/** - * Sets the currently used frequency registers (A or B) - * @param conf the AX5043 configuration handler - * @param f the frequency mode (A or B) - * @return 0 on success or appropriate negative error code - */ -int ax5043_freqsel(ax5043_conf_t *conf, freq_mode_t f) { - if (!is_ax5043_conf_valid(conf)) { - return -PQWS_INVALID_PARAM; - } - - if (f != FREQA_MODE && f != FREQB_MODE) { - return -PQWS_INVALID_PARAM; - } - conf->freqsel = f; - return PQWS_SUCCESS; -} - -/** - * Sets the TX frequency synthesizer related configuration registers. - * @param conf the AX5043 configuration handler - * @return 0 on success or appropriate negative error code - */ -int ax5043_set_tx_synth(ax5043_conf_t *conf) { - int ret; - uint8_t val; - if (!is_ax5043_conf_valid(conf)) { - return -PQWS_INVALID_PARAM; - } - - switch (conf->freqsel) { - case FREQA_MODE: - val = 0x0; - break; - case FREQB_MODE: - val = 1 << 7; - break; - default: - return -PQWS_INVALID_PARAM; - } - - /* Bypass external filter and use 100 kHZ loop bandwidth */ - val |= BIT(3) | BIT(0); - ret = ax5043_spi_write_8(conf, AX5043_REG_PLLLOOP, val); - if (ret) { - return ret; - } - - /* - * Set the charge pump current based on the loop bandwidth - * 68 uA @ 100 kHZ - */ - ret = ax5043_spi_write_8(conf, AX5043_REG_PLLCPI, (uint8_t) (68 / 8.5)); - if (ret) { - return ret; - } - ret = ax5043_spi_write_8(conf, AX5043_REG_XTALCAP, 0); - return ret; -} - -/** - * Sets the PLL related configuration registers. - * @param conf the AX5043 configuration handler - * @return 0 on success or appropriate negative error code - */ -int ax5043_set_pll_params(ax5043_conf_t *conf) { - int ret; - uint8_t i = 8; - if (!is_ax5043_conf_valid(conf)) { - return -PQWS_INVALID_PARAM; - } - - /* Set VCO to manual */ - ret = ax5043_spi_write_8(conf, AX5043_REG_PLLVCOI, - AX5043_PLLVCOI_MANUAL | (1250 / 50)); - if (ret) { - return ret; - } - - /* - * According to the manual PLL ranging clock should be less than 1/10 - * of the PLL loop bandwidth. The smallest PLL bandwidth configuration - * is 100 kHz. - */ - // This this next line contains an error - //while (conf->f_xtal / (uint32_t) (1 << i) > 10000) { - while (conf->f_xtal / (uint32_t) (1 << i) > 100000) { - i++; - } - i = i > 15 ? 15 : i; - i = i < 8 ? 8 : i; - ret = ax5043_spi_write_8(conf, AX5043_REG_PLLRNGCLK, (uint8_t) (i - 8)); - return ret; -} - -/** - * Performs auto-ranging using the frequency registers configured by - * ax5043_freqsel(). - * - * @param conf the AX5043 configuration handler - * @return 0 on success or appropriate negative error code - */ -int ax5043_autoranging(ax5043_conf_t *conf) { - int ret = PQWS_SUCCESS; - uint16_t pllranging_reg; - uint8_t val = 0; - - if (!is_ax5043_conf_valid(conf)) { - return -PQWS_INVALID_PARAM; - } - - switch (conf->freqsel) { - case FREQA_MODE: - pllranging_reg = AX5043_REG_PLLRANGINGA; - break; - case FREQB_MODE: - pllranging_reg = AX5043_REG_PLLRANGINGB; - break; - default: - return -PQWS_INVALID_PARAM; - } - - /* Write the initial VCO setting and start autoranging */ - val = BIT(4) | AX5043_VCOR_INIT; - ret = ax5043_spi_write_8(conf, pllranging_reg, val); - if (ret) { - return ret; - } - - usleep(10); - val = 0; - /* Wait until the autoranging is complete */ - while ((val & BIT(4)) == 0) { - ret = ax5043_spi_read_8(conf, &val, pllranging_reg); - if (ret) { - return ret; - } - } - - if (val & BIT(5)) { - return -PQWS_AX5043_AUTORANGING_ERROR; - } - - return PQWS_SUCCESS; -} - -/** - * - * @param conf the AX5043 configuration handler - * @return 0 on success or appropriate negative error code - */ -int ax5043_aprs_framing_setup(ax5043_conf_t *conf) { - int ret = PQWS_SUCCESS; - uint8_t val = 0; - - if (!is_ax5043_conf_valid(conf)) { - return -PQWS_INVALID_PARAM; - } - - /* Set modulation */ - val = AX5043_MODULATION_AFSK; - ret = ax5043_spi_write_8(conf, AX5043_REG_MODULATION, val); - if (ret) { - return ret; - } - - // To set the space frequency, 1070 - // 1070 * 2^18 / fXTAL -> 1070 * 2^18 / 16000000 -> 18 -> 0x12 - - // To set the space frequency, 1200 - // 1200 * 2^18 / fXTAL -> 1200 * 2^18 / 16000000 -> 20 -> 0x14 - - ret = ax5043_spi_write_16(conf, AX5043_REG_AFSKSPACE1, 0x24); - if (ret) { - return ret; - } - - // To set the mark frequency, 1270 - // 1270 * 2^18 / fXTAL -> 1270 * 2^18 / 16000000 -> 21 -> 0x15 - - // To set the mark frequency, 1400 - // 1400 * 2^18 / fXTAL -> 1400 * 2^18 / 16000000 -> 23 -> 0x17 - - ret = ax5043_spi_write_16(conf, AX5043_REG_AFSKMARK1, 0x14); - if (ret) { - return ret; - } - - /* - * As we do not use any external filter, try to filter from - * the AX5043 the signal - */ - ret = ax5043_spi_write_8(conf, AX5043_REG_MODCFGF, - AX5043_FREQSHAPE_GAUSSIAN_BT_05); - if (ret) { - return ret; - } - - /* Set HDLC encoding: Differential = 1, Inverse = 1, Scrambling = 1 */ - //ax5043_spi_write_8(conf, AX5043_REG_ENCODING, - /* Set HDLC encoding: Differential = 1, Inverse = 1, Scrambling = 1 */ - ax5043_spi_write_8(conf, AX5043_REG_ENCODING, - AX5043_ENC_DIFF | AX5043_ENC_INV); - - /* HDLC framing */ - ax5043_spi_write_8(conf, AX5043_REG_FRAMING, - AX5043_HDLC_FRAMING | AX5043_CRC16_CCITT); - return ret; -} - -static int __tx_frame_end(ax5043_conf_t *conf) { - int ret; - - ax5043_enable_pwramp(conf, AX5043_EXT_PA_DISABLE); - - /* Set AX5043 to power down mode */ - ret = ax5043_set_power_mode(conf, POWERDOWN); - __tx_active = 0; - return ret; -} - -static int __tx_frame(ax5043_conf_t *conf, const uint8_t *in, uint32_t len, - uint8_t preamble_len, uint8_t postamble_len, uint32_t timeout_ms) { - int ret = PQWS_SUCCESS; - uint8_t data_cmd[3] = { AX5043_FIFO_VARIABLE_DATA_CMD, 0, 0 }; - size_t chunk_size = 0; - size_t avail; - uint8_t val; - uint32_t start = millis(); - - /* - * Apply preamble and postamble repetition length. Rest of the fields should - * remain unaltered - */ - __preamble_cmd[2] = preamble_len; - __postamble_cmd[2] = postamble_len; - - memcpy(__tx_fifo_chunk, __preamble_cmd, sizeof(__preamble_cmd)); - chunk_size = sizeof(__preamble_cmd); - __tx_buf_idx = 0; - - /* - * Always leave some space for the postamble. This greatly reduces the - * complexity of dealing with some corner cases - */ - avail = min_ul( - AX5043_FIFO_MAX_SIZE - sizeof(__preamble_cmd) - sizeof(data_cmd) - - sizeof(__postamble_cmd), len); - if (len == avail) { - data_cmd[1] = (uint8_t) (len + 1); - data_cmd[2] = AX5043_FIFO_PKTEND; - __tx_remaining = 0; - memcpy(__tx_fifo_chunk + chunk_size, data_cmd, sizeof(data_cmd)); - chunk_size += sizeof(data_cmd); - memcpy(__tx_fifo_chunk + chunk_size, in, len); - chunk_size += len; - /* - * At this point we are sure that the whole frame + postamble can fit in - * the FIFO chunk - */ - memcpy(__tx_fifo_chunk + chunk_size, __postamble_cmd, - sizeof(__postamble_cmd)); - chunk_size += sizeof(__postamble_cmd); - single_fifo_access = 1; - } else { - data_cmd[1] = (uint8_t) (avail + 1); - data_cmd[2] = 0; - memcpy(__tx_fifo_chunk + chunk_size, data_cmd, sizeof(data_cmd)); - chunk_size += sizeof(data_cmd); - memcpy(__tx_fifo_chunk + chunk_size, in, avail); - chunk_size += avail; - - memcpy(__tx_buf, in + avail, len - avail); - __tx_remaining = (uint32_t) (len - avail); - single_fifo_access = 0; - } - - /* Set AX5043 to FULLTX mode */ - ret = ax5043_set_power_mode(conf, FULLTX); - if (ret) { - return ret; - } - - ax5043_spi_wait_xtal(conf, 100); - - /* Wait for the FIFO to become ready */ - val = 0; - while (!val) { - ax5043_spi_read_8(conf, &val, AX5043_REG_POWSTAT); - /* Select only the modem power state */ - val &= AX5043_SVMODEM; - if (millis() - start > timeout_ms) { - ret = -PQWS_TIMEOUT; - break; - } - } - - /* Fire-up the first data to the FIFO */ - ret = ax5043_spi_write(conf, AX5043_REG_FIFODATA, __tx_fifo_chunk, - (uint32_t) chunk_size); - if (ret) { - return ret; - } - __tx_active = 1; - /* Commit to FIFO ! */ - ret = ax5043_spi_write_8(conf, AX5043_REG_FIFOSTAT, AX5043_FIFO_COMMIT_CMD); - - return ret; -} - -int ax5043_tx_frame(ax5043_conf_t *conf, const uint8_t *in, uint32_t len, - uint8_t preamble_len, uint8_t postamble_len, uint32_t timeout_ms) { - int ret = 0; - - /* Wait for the previous frame to be transmitted */ - while (__tx_active) { - ret++; - } - - ret = ax5043_enable_pwramp(conf, AX5043_EXT_PA_ENABLE); - if (ret) { - return ret; - } - - ret = __tx_frame(conf, in, len, preamble_len, postamble_len, timeout_ms); - return ret; -} - -/** - * Wait the crystal to become ready - * @param conf the AX5043 configuration handler - * @param timeout_ms the timeout in milliseconds - * @return 0 on success or appropriate negative error code - */ -int ax5043_spi_wait_xtal(ax5043_conf_t *conf, uint32_t timeout_ms) { - int ret; - uint8_t val = 0x0; - uint32_t start = millis(); - - while (!val) { - ret = ax5043_spi_read_8(conf, &val, AX5043_REG_XTALSTATUS); - if (ret) { - return ret; - } - if ((millis() - start) > timeout_ms) { - return -PQWS_TIMEOUT; - } - } - return 0; -} - -int ax5043_spi_read_8(ax5043_conf_t *conf, uint8_t *out, uint16_t reg) { - int ret = PQWS_SUCCESS; - - if (!is_ax5043_conf_valid(conf)) { - return -PQWS_INVALID_PARAM; - } - *out = ax5043ReadReg(reg); - - return ret; -} - -int ax5043_spi_read_16(ax5043_conf_t *conf, uint16_t *out, uint16_t reg) { - int ret = PQWS_SUCCESS; - - if (!is_ax5043_conf_valid(conf)) { - return -PQWS_INVALID_PARAM; - } - - *out = ax5043ReadReg2(reg); - - return ret; -} - -int ax5043_spi_read_24(ax5043_conf_t *conf, uint32_t *out, uint16_t reg) { - int ret = PQWS_SUCCESS; - - if (!is_ax5043_conf_valid(conf)) { - return -PQWS_INVALID_PARAM; - } - - *out = ax5043ReadReg3(reg); - - return ret; -} - -int ax5043_spi_read_32(ax5043_conf_t *conf, uint32_t *out, uint16_t reg) { - int ret = PQWS_SUCCESS; - - if (!is_ax5043_conf_valid(conf)) { - return -PQWS_INVALID_PARAM; - } - - *out = ax5043ReadReg4(reg); - - return ret; -} - -int ax5043_spi_write(ax5043_conf_t *conf, uint16_t reg, const uint8_t *in, - uint32_t len) { - int ret = PQWS_SUCCESS; - - if (!is_ax5043_conf_valid(conf)) { - return -PQWS_INVALID_PARAM; - } - - ax5043WriteRegN(reg, in, len); - - return ret; -} - -int ax5043_spi_write_8(ax5043_conf_t *conf, uint16_t reg, uint8_t in) { - if (!is_ax5043_conf_valid(conf)) { - return -PQWS_INVALID_PARAM; - } - - //printf("Reg\t%04x\t%02x\n", reg, in); - - ax5043WriteReg(reg, in); - - return PQWS_SUCCESS; -} - -int ax5043_spi_write_16(ax5043_conf_t *conf, uint16_t reg, uint16_t in) { - if (!is_ax5043_conf_valid(conf)) { - return -PQWS_INVALID_PARAM; - } - - //printf("Reg\t%04x\t%02x\n", reg, (in >> 8)&0xFF); - //printf("Reg\t%04x\t%02x\n", reg+1, (in >> 0)&0xFF); - - ax5043WriteReg2(reg, in); - - return PQWS_SUCCESS; -} - -int ax5043_spi_write_24(ax5043_conf_t *conf, uint16_t reg, uint32_t in) { - if (!is_ax5043_conf_valid(conf)) { - return -PQWS_INVALID_PARAM; - } - - //printf("Reg\t%04x\t%02x\n", reg, (in >> 16)&0xFF); - //printf("Reg\t%04x\t%02x\n", reg+1, (in >> 8)&0xFF); - //printf("Reg\t%04x\t%02x\n", reg+2, (in >> 0)&0xFF); - - ax5043WriteReg3(reg, in); - - return PQWS_SUCCESS; -} - -int ax5043_spi_write_32(ax5043_conf_t *conf, uint16_t reg, uint32_t in) { - if (!is_ax5043_conf_valid(conf)) { - return -PQWS_INVALID_PARAM; - } - - //printf("Reg\t%04x\t%02x\n", reg, (in >> 24)&0xFF); - //printf("Reg\t%04x\t%02x\n", reg+1, (in >> 16)&0xFF); - //printf("Reg\t%04x\t%02x\n", reg+2, (in >> 8)&0xFF); - //printf("Reg\t%04x\t%02x\n", reg+3, (in >> 0)&0xFF); - - ax5043WriteReg4(reg, in); - - return PQWS_SUCCESS; -} - -/** - * Sets properly some undocumented TX registers - * @param conf the AX5043 configuration handler - * @return 0 on success or appropriate negative error code - */ -static inline int set_tx_black_magic_regs(ax5043_conf_t *conf) { - int ret; - ret = ax5043_spi_write_8(conf, 0xF00, 0x0F); - if (ret) { - return ret; - } - - ret = ax5043_spi_write_8(conf, 0xF0C, 0x0); - if (ret) { - return ret; - } - - // Added by Jonathan Brandenburg - ret = ax5043_spi_write_8(conf, 0xF0D, 0x03); - if (ret) { - return ret; - } - - // Added by Jonathan Brandenburg - ret = ax5043_spi_write_8(conf, 0xF10, 0x03); - if (ret) { - return ret; - } - - // The following line is used for a TCXO - //ret = ax5043_spi_write_8(conf, 0xF11, 0x0); - // The following line is used for a crystal - ret = ax5043_spi_write_8(conf, 0xF11, 0x07); - if (ret) { - return ret; - } - - ret = ax5043_spi_write_8(conf, 0xF1C, 0x07); - if (ret) { - return ret; - } - - ret = ax5043_spi_write_8(conf, 0xF44, 0x24); - if (ret) { - return ret; - } - - /* Dafuq? Got it from RadioLab */ - ret = ax5043_spi_write_8(conf, 0xF18, 0x06); - return ret; -} - -/** - * Enables/Disables the power amplifier pin - * @param conf the AX5043 configuration handler - * @param enable 1 to enable 0 to disable - * @return 0 on success or appropriate negative error code - */ -int ax5043_enable_pwramp(ax5043_conf_t *conf, uint8_t enable) { - int ret; - ax5043_set_antsel(conf, enable); - ret = ax5043_spi_write_8(conf, AX5043_REG_PWRAMP, ~enable & 0x1); - - if (ret) { - usleep(PWRAMP_RAMP_PERIOD_US); - } - return ret; -} - -int ax5043_set_antsel(ax5043_conf_t *conf, uint8_t val) { - return ax5043_spi_write_8(conf, AX5043_REG_PINFUNCANTSEL, val & 0x1); -} - -/** - * Wait for the AX5043 to finish transmitting, putting new data in the FIFO as space becomes available - * @return 0 on success, or appropriate negative error code - */ -int ax5043_wait_for_transmit() { - if (!single_fifo_access) { - while (__tx_active) { - static int transmittedPostamble = 0; - - //usleep(100); - - int ret; - uint8_t data_cmd[3] = { AX5043_FIFO_VARIABLE_DATA_CMD, 0, 0 }; - size_t avail; - size_t chunk_size; - - if (!__ax5043_conf) { - return -PQWS_INVALID_PARAM; - } - - /* Determine if TX is done */ - uint8_t radiostate = 0; - ret = ax5043_spi_read_8(__ax5043_conf, &radiostate, - AX5043_REG_RADIOSTATE); - if (ret) { - return ret; - } - radiostate &= 0x0f; - - if (radiostate == 0) { - /* tx is done */ - __tx_frame_end(__ax5043_conf); - transmittedPostamble = 0; - printf("INFO: TX done\n"); - return PQWS_SUCCESS; - } - - /* Determine FIFO free space */ - uint16_t fifofree = 0; - ret = ax5043_spi_read_16(__ax5043_conf, &fifofree, - AX5043_REG_FIFOFREE1); - if (ret) { - return ret; - } - - /* If FIFO has free space fill in data */ - if (fifofree > AX5043_FIFO_FREE_THR && (__tx_remaining || !transmittedPostamble)) { - - /* Always left some space for the postamble for a simplified logic */ - avail = min_ul( - AX5043_FIFO_FREE_THR - sizeof(data_cmd) - sizeof(__postamble_cmd), - __tx_remaining); - - data_cmd[1] = (uint8_t) (avail + 1); - chunk_size = sizeof(data_cmd) + avail; - memcpy(__tx_fifo_chunk + sizeof(data_cmd), __tx_buf + __tx_buf_idx, - avail); - - if (avail == __tx_remaining) { - transmittedPostamble = 1; - - data_cmd[2] = AX5043_FIFO_PKTEND; - memcpy(__tx_fifo_chunk + chunk_size, __postamble_cmd, - sizeof(__postamble_cmd)); - chunk_size += sizeof(__postamble_cmd); - } - memcpy(__tx_fifo_chunk, data_cmd, sizeof(data_cmd)); - ax5043_spi_write(__ax5043_conf, AX5043_REG_FIFODATA, - __tx_fifo_chunk, (uint32_t) chunk_size); - /* Commit to FIFO ! */ - ret = ax5043_spi_write_8(__ax5043_conf, AX5043_REG_FIFOSTAT, - AX5043_FIFO_COMMIT_CMD); - - __tx_remaining -= (uint32_t) avail; - __tx_buf_idx += avail; - - } - } - } else { - while (__tx_active) { - int ret; - /* Determine if TX is done */ - uint8_t radiostate = 0; - ret = ax5043_spi_read_8(__ax5043_conf, &radiostate, - AX5043_REG_RADIOSTATE); - if (ret) { - return ret; - } - radiostate &= 0x0f; - if (radiostate == 0) { - /* tx is done */ - __tx_active = 0; - printf("INFO: TX done\n"); - } - } - } - - return PQWS_SUCCESS; -} diff --git a/cw/ax5043.h b/cw/ax5043.h deleted file mode 100644 index 855466cc..00000000 --- a/cw/ax5043.h +++ /dev/null @@ -1,582 +0,0 @@ -/* - * A sample application transmitting AFSK at 1200 baud - * - * Portions Copyright (C) 2018 Libre Space Foundation - * Portions Copyright (C) 2018 Jonathan Brandenburg - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef AX5043_H_ -#define AX5043_H_ - -#include - -#define FREQUENCY_OFFSET -80000 - -#define APRS_VHF 440390000 - -/****************************************************************************** - ************************* RF Configuration *********************************** - *****************************************************************************/ -#define RX_FREQ_HZ (APRS_VHF + FREQUENCY_OFFSET) -#define TX_FREQ_HZ (APRS_VHF + FREQUENCY_OFFSET) - -/* Reference Oscillator frequency */ -#define XTAL_FREQ_HZ 16000000 - -/** - * The maximum allowed frame size - */ -#define MAX_FRAME_LEN 1024 - -#define RX_BAUDRATE 1200 -#define TX_BAUDRATE 1200 - -#define MIN_RF_FREQ_INT_VCO_RFDIV0 800000000 -#define MAX_RF_FREQ_INT_VCO_RFDIV0 1050000000 - -#define MIN_RF_FREQ_INT_VCO_RFDIV1 (MIN_RF_FREQ_INT_VCO_RFDIV0 / 2) -#define MAX_RF_FREQ_INT_VCO_RFDIV1 (MAX_RF_FREQ_INT_VCO_RFDIV0 / 2) - -#define MIN_RF_FREQ_EXT_VCO_RFDIV0 54000000 -#define MAX_RF_FREQ_EXT_VCO_RFDIV0 525000000 - -#define MIN_RF_FREQ_EXT_VCO_RFDIV1 (MIN_RF_FREQ_EXT_VCO_RFDIV0 / 2) -#define MAX_RF_FREQ_EXT_VCO_RFDIV1 (MAX_RF_FREQ_EXT_VCO_RFDIV0 / 2) - -/** - * Ramp up/Ramp down period of the power amplifier in microseconds - */ -#define PWRAMP_RAMP_PERIOD_US 200 - -/****************************************************************************** - ******************** AX5043 control SPI registers *************************** - *****************************************************************************/ - -/* Status and test registers */ -#define AX5043_REG_REV 0x0 -#define AX5043_REG_SCRATCH 0x1 - -/* Power and voltage regulator */ -#define AX5043_REG_PWRMODE 0x2 -#define AX5043_REG_POWSTAT 0x3 -#define AX5043_REG_POWSTICKYSTAT 0x4 -#define AX5043_REG_POWIRQMASK 0x5 - -/* Interrupt control */ -#define AX5043_REG_IRQMASK1 0x6 -#define AX5043_REG_IRQMASK0 0x7 -#define AX5043_REG_RADIOEVENTMASK1 0x8 -#define AX5043_REG_RADIOEVENTMASK0 0x9 - -#define AX5043_REG_IRQREQUEST1 0xC -#define AX5043_REG_IRQREQUEST0 0xD -#define AX5043_REG_RADIOEVENTREQ1 0xE -#define AX5043_REG_RADIOEVENTREQ0 0xF - -/* Modulation and framing */ -#define AX5043_REG_MODULATION 0x010 -#define AX5043_REG_ENCODING 0x011 -#define AX5043_REG_FRAMING 0x012 -#define AX5043_REG_CRCINIT3 0x014 -#define AX5043_REG_CRCINIT2 0x015 -#define AX5043_REG_CRCINIT1 0x016 -#define AX5043_REG_CRCINIT0 0x017 - -/* FEC */ -#define AX5043_REG_FEC 0x018 -#define AX5043_REG_FECSYNC 0x019 -#define AX5043_REG_FECSTATUS 0x01A - -/* Status */ -#define AX5043_REG_RADIOSTATE 0x01C -#define AX5043_REG_XTALSTATUS 0x01D - -/* Pin configuration */ -#define AX5043_REG_PINSTATE 0x20 -#define AX5043_REG_PINFUNCSYSCLK 0x21 -#define AX5043_REG_PINFUNCDCLK 0x22 -#define AX5043_REG_PINFUNCDATA 0x23 -#define AX5043_REG_PINFUNCIRQ 0x24 -#define AX5043_REG_PINFUNCANTSEL 0x25 -#define AX5043_REG_PINFUNCPWRAMP 0x26 -#define AX5043_REG_PWRAMP 0x27 - -/* FIFO control */ -#define AX5043_REG_FIFOSTAT 0x28 -#define AX5043_REG_FIFODATA 0x29 -#define AX5043_REG_FIFOCOUNT1 0x2A -#define AX5043_REG_FIFOCOUNT0 0x2B -#define AX5043_REG_FIFOFREE1 0x2C -#define AX5043_REG_FIFOFREE0 0x2D -#define AX5043_REG_FIFOTHRESH1 0x2E -#define AX5043_REG_FIFOTHRESH0 0x2F - -/* Frequency Synthesizer */ -#define AX5043_REG_PLLLOOP 0x30 -#define AX5043_REG_PLLCPI 0x31 -#define AX5043_REG_PLLVCODIV 0x32 -#define AX5043_REG_PLLRANGINGA 0x33 -#define AX5043_REG_FREQA3 0x34 -#define AX5043_REG_FREQA2 0x35 -#define AX5043_REG_FREQA1 0x36 -#define AX5043_REG_FREQA0 0x37 -#define AX5043_REG_PLLLOOPBOOST 0x38 -#define AX5043_REG_PLLCPIBOOST 0x39 -#define AX5043_REG_PLLRANGINGB 0x3B -#define AX5043_REG_FREQB3 0x3C -#define AX5043_REG_FREQB2 0x3D -#define AX5043_REG_FREQB1 0x3E -#define AX5043_REG_FREQB0 0x3F - -/* RSSI */ -#define AX5043_REG_RSSI 0x40 -#define AX5043_REG_BGNDRSSI 0x41 -#define AX5043_REG_DIVERSITY 0x42 -#define AX5043_REG_AGCCOUNTER 0x43 - -/* Receiver Tracking */ -#define AX5043_REG_TRKDATARATE2 0x45 -#define AX5043_REG_TRKDATARATE1 0x46 -#define AX5043_REG_TRKDATARATE0 0x47 -#define AX5043_REG_TRKAMPL1 0x48 -#define AX5043_REG_TRKAMPL0 0x49 -#define AX5043_REG_TRKPHASE1 0x4A -#define AX5043_REG_TRKPHASE0 0x4B -#define AX5043_REG_TRKRFFREQ2 0x4D -#define AX5043_REG_TRKRFFREQ1 0x4E -#define AX5043_REG_TRKRFFREQ0 0x4F -#define AX5043_REG_TRKFREQ1 0x50 -#define AX5043_REG_TRKFREQ0 0x51 -#define AX5043_REG_TRKFSKDEMOD1 0x52 -#define AX5043_REG_TRKFSKDEMOD0 0x53 - -/* Timers */ -#define AX5043_REG_TIMER2 0x59 -#define AX5043_REG_TIMER1 0x5A -#define AX5043_REG_TIMER0 0x5B - -/* Wakeup timer */ -#define AX5043_REG_WAKEUPTIMER1 0x68 -#define AX5043_REG_WAKEUPTIMER0 0x69 -#define AX5043_REG_WAKEUP1 0x6A -#define AX5043_REG_WAKEUP0 0x6B -#define AX5043_REG_WAKEUPFREQ1 0x6C -#define AX5043_REG_WAKEUPFREQ0 0x6D -#define AX5043_REG_WAKEUPXOEARLY 0x6E - -/* PHY related registers*/ -#define AX5043_REG_IFFREQ1 0x100 -#define AX5043_REG_IFFREQ0 0x101 -#define AX5043_REG_DECIMATION 0x102 -#define AX5043_REG_RXDATARATE2 0x103 -#define AX5043_REG_RXDATARATE1 0x104 -#define AX5043_REG_RXDATARATE0 0x105 -#define AX5043_REG_MAXDROFFSET2 0x106 -#define AX5043_REG_MAXDROFFSET1 0x107 -#define AX5043_REG_MAXDROFFSET0 0x108 -#define AX5043_REG_MAXRFOFFSET2 0x109 -#define AX5043_REG_MAXRFOFFSET1 0x10A -#define AX5043_REG_MAXRFOFFSET0 0x10B -#define AX5043_REG_FSKDMAX1 0x10C -#define AX5043_REG_FSKDMAX0 0x10D -#define AX5043_REG_FSKDMIN1 0x10E -#define AX5043_REG_FSKDMIN0 0x10F -#define AX5043_REG_AFSKSPACE1 0x110 -#define AX5043_REG_AFSKSPACE0 0x111 -#define AX5043_REG_AFSKMARK1 0x112 -#define AX5043_REG_AFSKMARK0 0x113 -#define AX5043_REG_AFSKCTRL 0x114 -#define AX5043_REG_AMPLFILTER 0x115 -#define AX5043_REG_FREQUENCYLEAK 0x116 -#define AX5043_REG_RXPARAMSETS 0x117 -#define AX5043_REG_RXPARAMCURSET 0x118 - -/* Receiver Parameter Set 0 */ -#define AX5043_REG_AGCGAIN0 0x120 -#define AX5043_REG_AGCTARGET0 0x121 -#define AX5043_REG_AGCAHYST0 0x122 -#define AX5043_REG_AGCMINMAX0 0x123 -#define AX5043_REG_TIMEGAIN0 0x124 -#define AX5043_REG_DRGAIN0 0x125 -#define AX5043_REG_PHASEGAIN0 0x126 -#define AX5043_REG_FREQGAINA0 0x127 -#define AX5043_REG_FREQGAINB0 0x128 -#define AX5043_REG_FREQGAINC0 0x129 -#define AX5043_REG_FREQGAIND0 0x12A -#define AX5043_REG_AMPLGAIN0 0x12B -#define AX5043_REG_FREQDEV10 0x12C -#define AX5043_REG_FREQDEV00 0x12D -#define AX5043_REG_FOURFSK0 0x12E -#define AX5043_REG_BBOFFSRES0 0x12F - -/* Receiver Parameter Set 1 */ -#define AX5043_REG_AGCGAIN1 0x130 -#define AX5043_REG_AGCTARGET1 0x131 -#define AX5043_REG_AGCAHYST1 0x132 -#define AX5043_REG_AGCMINMAX1 0x133 -#define AX5043_REG_TIMEGAIN1 0x134 -#define AX5043_REG_DRGAIN1 0x135 -#define AX5043_REG_PHASEGAIN1 0x136 -#define AX5043_REG_FREQGAINA1 0x137 -#define AX5043_REG_FREQGAINB1 0x138 -#define AX5043_REG_FREQGAINC1 0x139 -#define AX5043_REG_FREQGAIND1 0x13A -#define AX5043_REG_AMPLGAIN1 0x13B -#define AX5043_REG_FREQDEV11 0x13C -#define AX5043_REG_FREQDEV01 0x13D -#define AX5043_REG_FOURFSK1 0x13E -#define AX5043_REG_BBOFFSRES1 0x13F - -/* Receiver Parameter Set 2 */ -#define AX5043_REG_AGCGAIN2 0x140 -#define AX5043_REG_AGCTARGET2 0x141 -#define AX5043_REG_AGCAHYST2 0x142 -#define AX5043_REG_AGCMINMAX2 0x143 -#define AX5043_REG_TIMEGAIN2 0x144 -#define AX5043_REG_DRGAIN2 0x145 -#define AX5043_REG_PHASEGAIN2 0x146 -#define AX5043_REG_FREQGAINA2 0x147 -#define AX5043_REG_FREQGAINB2 0x148 -#define AX5043_REG_FREQGAINC2 0x149 -#define AX5043_REG_FREQGAIND2 0x14A -#define AX5043_REG_AMPLGAIN2 0x14B -#define AX5043_REG_FREQDEV12 0x14C -#define AX5043_REG_FREQDEV02 0x14D -#define AX5043_REG_FOURFSK2 0x14E -#define AX5043_REG_BBOFFSRES2 0x14F - -/* Receiver Parameter Set 3 */ -#define AX5043_REG_AGCGAIN3 0x150 -#define AX5043_REG_AGCTARGET3 0x151 -#define AX5043_REG_AGCAHYST3 0x152 -#define AX5043_REG_AGCMINMAX3 0x153 -#define AX5043_REG_TIMEGAIN3 0x154 -#define AX5043_REG_DRGAIN3 0x155 -#define AX5043_REG_PHASEGAIN3 0x156 -#define AX5043_REG_FREQGAINA3 0x157 -#define AX5043_REG_FREQGAINB3 0x158 -#define AX5043_REG_FREQGAINC3 0x159 -#define AX5043_REG_FREQGAIND3 0x15A -#define AX5043_REG_AMPLGAIN3 0x15B -#define AX5043_REG_FREQDEV13 0x15C -#define AX5043_REG_FREQDEV03 0x15D -#define AX5043_REG_FOURFSK3 0x15E -#define AX5043_REG_BBOFFSRES3 0x15F - -/* Transmitter Parameters */ -#define AX5043_REG_MODCFGF 0x160 -#define AX5043_REG_FSKDEV2 0x161 -#define AX5043_REG_FSKDEV1 0x162 -#define AX5043_REG_FSKDEV0 0x163 -#define AX5043_REG_MODCFGA 0x164 -#define AX5043_REG_TXRATE2 0x165 -#define AX5043_REG_TXRATE1 0x166 -#define AX5043_REG_TXRATE0 0x167 -#define AX5043_REG_TXPWRCOEFFA1 0x168 -#define AX5043_REG_TXPWRCOEFFA0 0x169 -#define AX5043_REG_TXPWRCOEFFB1 0x16A -#define AX5043_REG_TXPWRCOEFFB0 0x16B -#define AX5043_REG_TXPWRCOEFFC1 0x16C -#define AX5043_REG_TXPWRCOEFFC0 0x16D -#define AX5043_REG_TXPWRCOEFFD1 0x16E -#define AX5043_REG_TXPWRCOEFFD0 0x16F -#define AX5043_REG_TXPWRCOEFFE1 0x170 -#define AX5043_REG_TXPWRCOEFFE0 0x171 - -/* PLL parameters */ -#define AX5043_REG_PLLVCOI 0x180 -#define AX5043_REG_PLLVCOIR 0x181 -#define AX5043_REG_PLLLOCKDET 0x182 -#define AX5043_REG_PLLRNGCLK 0x183 - -/* Crystal Oscillator */ -#define AX5043_REG_XTALCAP 0x184 - -/* Baseband */ -#define AX5043_REG_BBTUNE 0x188 -#define AX5043_REG_BBOFFSCAP 0x189 - -/* MAC parameters */ - -/* Packet Format */ -#define AX5043_REG_PKTADDRCFG 0x200 -#define AX5043_REG_PKTLENCFG 0x201 -#define AX5043_REG_PKTLENOFFSET 0x202 -#define AX5043_REG_PKTMAXLEN 0x203 -#define AX5043_REG_PKTADDR3 0x204 -#define AX5043_REG_PKTADDR2 0x205 -#define AX5043_REG_PKTADDR1 0x206 -#define AX5043_REG_PKTADDR0 0x207 -#define AX5043_REG_PKTADDRMASK3 0x208 -#define AX5043_REG_PKTADDRMASK2 0x209 -#define AX5043_REG_PKTADDRMASK1 0x20A -#define AX5043_REG_PKTADDRMASK0 0x20B - -/* Pattern Match */ -#define AX5043_REG_MATCH0PAT3 0x210 -#define AX5043_REG_MATCH0PAT2 0x211 -#define AX5043_REG_MATCH0PAT1 0x212 -#define AX5043_REG_MATCH0PAT0 0x213 -#define AX5043_REG_MATCH0LEN 0x214 -#define AX5043_REG_MATCH0MIN 0x215 -#define AX5043_REG_MATCH0MAX 0x216 -#define AX5043_REG_MATCH1PAT1 0x218 -#define AX5043_REG_MATCH1PAT0 0x219 -#define AX5043_REG_MATCH1LEN 0x21C -#define AX5043_REG_MATCH1MIN 0x21D -#define AX5043_REG_MATCH1MAX 0x21E - -/* Packet Controller */ -#define AX5043_REG_TMGTXBOOST 0x220 -#define AX5043_REG_TMGTXSETTLE 0x221 -#define AX5043_REG_TMGRXBOOST 0x223 -#define AX5043_REG_TMGRXSETTLE 0x224 -#define AX5043_REG_TMGRXOFFSACQ 0x225 -#define AX5043_REG_TMGRXCOARSEAGC 0x226 -#define AX5043_REG_TMGRXAGC 0x227 -#define AX5043_REG_TMGRXRSSI 0x228 -#define AX5043_REG_TMGRXPREAMBLE1 0x229 -#define AX5043_REG_TMGRXPREAMBLE2 0x22A -#define AX5043_REG_TMGRXPREAMBLE3 0x22B -#define AX5043_REG_RSSIREFERENCE 0x22C -#define AX5043_REG_RSSIABSTHR 0x22D -#define AX5043_REG_BGNDRSSIGAIN 0x22E -#define AX5043_REG_BGNDRSSITHR 0x22F -#define AX5043_REG_PKTCHUNKSIZE 0x230 -#define AX5043_REG_PKTMISCFLAGS 0x231 -#define AX5043_REG_PKTSTOREFLAGS 0x232 -#define AX5043_REG_PKTACCEPTFLAGS 0x233 - -/* Special Functions */ - -/* General Purpose ADC */ -#define AX5043_REG_GPADCCTRL 0x300 -#define AX5043_REG_GPADCPERIOD 0x301 -#define AX5043_REG_GPADC13VALUE1 0x308 -#define AX5043_REG_GPADC13VALUE0 0x309 - -/* Low Power Oscillator Calibration */ -#define AX5043_REG_LPOSCCONFIG 0x310 -#define AX5043_REG_LPOSCSTATUS 0x311 -#define AX5043_REG_LPOSCKFILT1 0x312 -#define AX5043_REG_LPOSCKFILT0 0x313 -#define AX5043_REG_LPOSCREF1 0x314 -#define AX5043_REG_LPOSCREF0 0x315 -#define AX5043_REG_LPOSCFREQ1 0x316 -#define AX5043_REG_LPOSCFREQ0 0x317 -#define AX5043_REG_LPOSCPER1 0x318 -#define AX5043_REG_LPOSCPER0 0x319 - -/* Performance Tuning Registers */ -#define AX5043_REG_XTALDIV 0xF35 - -/****************************************************************************** - ************************* Register values ************************************ - *****************************************************************************/ -#define AX5043_REV 0x51 -#define AX5043_SCRATCH_TEST 0xAA - -/* Power modes */ -#define AX5043_POWERDOWN 0x0 -#define AX5043_DEEPSLEEP BIT(0) -#define AX5043_STANDBY (BIT(2) | BIT(0)) -#define AX5043_FIFO_ENABLED (BIT(2) | BIT(1) |BIT(0)) -#define AX5043_RECEIVE_MODE (BIT(3)) -#define AX5043_RECEIVER_RUNNING (BIT(3) | BIT(0)) -#define AX5043_RECEIVER_WOR (BIT(3) | BIT(1) | BIT(0)) -#define AX5043_TRANSMIT_MODE (BIT(3) | BIT(2)) -#define AX5043_TRANSMIT_RUNNING (BIT(3) | BIT(2) | BIT(0)) -#define AX5043_FULLTX AX5043_TRANSMIT_RUNNING - -#define AX5043_PLLVCOI_MANUAL BIT(7) - -/** - * Modem Domain Voltage Regulator Ready - */ -#define AX5043_SVMODEM BIT(3) - -/** - * Init value for the VCO prior starting an autoranging - */ -#define AX5043_VCOR_INIT 8 - -#define AX5043_RFDIV0 0x0 -#define AX5043_RFDIV1 BIT(2) - -#define AX5043_FREQSHAPE_EXT_FILTER 0x0 -#define AX5043_FREQSHAPE_INVALID 0x1 -#define AX5043_FREQSHAPE_GAUSSIAN_BT_03 0x2 -#define AX5043_FREQSHAPE_GAUSSIAN_BT_05 0x3 - -/** - * FSK modulation mode - */ -#define AX5043_MODULATION_FSK BIT(3) - -/** - * AFSK modulation mode - */ -#define AX5043_MODULATION_AFSK (BIT(3)|BIT(1)) - -#define AX5043_ENC_INV BIT(0) -#define AX5043_ENC_DIFF BIT(1) -#define AX5043_ENC_SCRAM BIT(2) - -/** - * HDLC Framing mode - */ -#define AX5043_HDLC_FRAMING BIT(2) - -/** - * HDLC compliant CRC16 - */ -#define AX5043_CRC16_CCITT BIT(4) - -/** - * Set the FIFO to variable length data mode - */ -#define AX5043_FIFO_VARIABLE_DATA_CMD 0xe1 - -#define AX5043_FIFO_REPEATDATA_CMD (BIT(6) | BIT(5) | BIT(1)) - -/** - * FIFO commit command - */ -#define AX5043_FIFO_COMMIT_CMD BIT(2) -#define AX5043_FIFO_PKTSTART BIT(0) -#define AX5043_FIFO_PKTEND BIT(1) -#define AX5043_FIFO_NOCRC BIT(3) -#define AX5043_FIFO_RAW BIT(4) - -/** - * Maximum chuck that can be committed on the FIFO - */ -#define AX5043_PKTCHUNKSIZE_240 0xd - -#define AX5043_FIFO_MAX_SIZE 240 - -/** - * When this threshold of free bytes in the TX FIFO is reached, - * we'll put more data in the FIFO - */ -#define AX5043_FIFO_FREE_THR 128 - -/** - * TX antenna transmission mode - */ -#define AX5043_TX_SINGLE_ENDED BIT(1) -#define AX5043_TX_DIFFERENTIAL BIT(0) - -/** - * External PA Control - */ - -#define AX5043_EXT_PA_ENABLE 1 -#define AX5043_EXT_PA_DISABLE 0 - -/** - * Frequency mode A or B actually selects at which registers - * the frequency configuration should be written. - * - * This is quite handy for different RX/TX frequencies, to avoid - * writing every time the two different frequency configurations. - */ -typedef enum { - FREQA_MODE = 0, //!< FREQA_MODE - FREQB_MODE = 1 //!< FREQB_MODE -} freq_mode_t; - -typedef enum { - VCO_INTERNAL = 0, VCO_EXTERNAL = 1 -} vco_mode_t; - -typedef enum { - POWERDOWN, - DEEPSLEEP, - STANDBY, - FIFO_ENABLED, - RECEIVE_MODE, - RECEIVER_RUNNING, - RECEIVER_WOR, - TRANSMIT_MODE, - FULLTX -} power_mode_t; - -typedef struct { - uint32_t tx_freq; - uint32_t rx_freq; - uint32_t f_xtal; - uint8_t f_xtaldiv; - uint32_t tx_baudrate; - uint32_t rx_baudrate; - uint8_t rf_init; - freq_mode_t freqsel; - vco_mode_t vco; -} ax5043_conf_t; - -int ax5043_reset(ax5043_conf_t *conf); - -int ax5043_init(ax5043_conf_t *conf, uint32_t f_xtal, vco_mode_t vco); - -int ax5043_conf_tx_path(ax5043_conf_t *conf); - -int ax5043_set_tx_freq(ax5043_conf_t *conf, uint32_t freq); - -int ax5043_set_power_mode(ax5043_conf_t *conf, power_mode_t mode); - -int ax5043_set_tx_baud(ax5043_conf_t *conf, uint32_t baud); - -int ax5043_freqsel(ax5043_conf_t *conf, freq_mode_t f); - -int ax5043_set_tx_synth(ax5043_conf_t *conf); - -int ax5043_set_pll_params(ax5043_conf_t *conf); - -int ax5043_autoranging(ax5043_conf_t *conf); - -int ax5043_aprs_framing_setup(ax5043_conf_t *conf); - -int ax5043_tx_frame(ax5043_conf_t *conf, const uint8_t *in, uint32_t len, - uint8_t preamble_len, uint8_t postamble_len, uint32_t timeout_ms); - -int ax5043_spi_wait_xtal(ax5043_conf_t *conf, uint32_t timeout_ms); - -int ax5043_spi_read_8(ax5043_conf_t *conf, uint8_t *out, uint16_t reg); - -int ax5043_spi_read_16(ax5043_conf_t *conf, uint16_t *out, uint16_t reg); - -int ax5043_spi_read_24(ax5043_conf_t *conf, uint32_t *out, uint16_t reg); - -int ax5043_spi_read_32(ax5043_conf_t *conf, uint32_t *out, uint16_t reg); - -int ax5043_spi_write(ax5043_conf_t *conf, uint16_t reg, const uint8_t *in, - uint32_t len); - -int ax5043_spi_write_8(ax5043_conf_t *conf, uint16_t reg, uint8_t in); - -int ax5043_spi_write_16(ax5043_conf_t *conf, uint16_t reg, uint16_t in); - -int ax5043_spi_write_24(ax5043_conf_t *conf, uint16_t reg, uint32_t in); - -int ax5043_spi_write_32(ax5043_conf_t *conf, uint16_t reg, uint32_t in); - -int ax5043_enable_pwramp(ax5043_conf_t *conf, uint8_t enable); - -int ax5043_set_antsel(ax5043_conf_t *conf, uint8_t val); - -int ax5043_wait_for_transmit(); - -#endif /* AX5043_H_ */ diff --git a/cw/status.h b/cw/status.h deleted file mode 100644 index 9a212e96..00000000 --- a/cw/status.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * A sample application transmitting AFSK at 1200 baud - * - * Portions Copyright (C) 2018 Libre Space Foundation - * Portions Copyright (C) 2018 Jonathan Brandenburg - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef STATUS_H_ -#define STATUS_H_ - -/** - * Error codes of the PQWS. Users should return the negative of the error - * codes. NO_ERROR is set to zero. - */ -typedef enum { - PQWS_SUCCESS = 0, //!< All ok! - PQWS_INVALID_PARAM, //!< An invalid parameter was given - PQWS_MAX_SPI_TRANSFER_ERROR, //!< The requested SPI data transfer was larger than supported - PQWS_NO_RF_FOUND, //!< No suitable RF chip found - PQWS_AX5043_AUTORANGING_ERROR, //!< Auto ranging failed on AX5043 - PQWS_TIMEOUT //!< A timeout occurred -} pqws_error_t; - -#endif /* STATUS_H_ */ diff --git a/cw/utils.h b/cw/utils.h deleted file mode 100644 index f35ee2d0..00000000 --- a/cw/utils.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * A sample application transmitting AFSK at 1200 baud - * - * Portions Copyright (C) 2018 Libre Space Foundation - * Portions Copyright (C) 2018 Jonathan Brandenburg - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef UTILS_H_ -#define UTILS_H_ - -#include - -#define BIT(x) (1 << x) - -static inline size_t min_ul(size_t x, size_t y) { - size_t ret = x < y ? x : y; - return ret; -} - -/** - * - * @return the milliseconds from the start of the program. - * Time is handled based on TIM2 timer. - */ -static inline uint32_t millis() { - static struct timeval tv_start; - static int tv_start_initialized = 0; - if (!tv_start_initialized) { - gettimeofday(&tv_start, NULL); - } - - struct timeval tv_current; - gettimeofday(&tv_current, NULL); - - uint32_t millis_elapsed = 0; - millis_elapsed = (uint32_t) (tv_current.tv_sec - tv_start.tv_sec) * 1000; - millis_elapsed += (uint32_t) (tv_current.tv_usec - tv_start.tv_usec) / 1000; - return millis_elapsed; -} - -#endif /* UTILS_H_ */