diff --git a/PiFmRds b/PiFmRds deleted file mode 160000 index e4e246e8..00000000 --- a/PiFmRds +++ /dev/null @@ -1 +0,0 @@ -Subproject commit e4e246e8d86203c867227d6c8f8b6ab71def39ae diff --git a/afsk.wav b/afsk.wav new file mode 100644 index 00000000..ade8de4d Binary files /dev/null and b/afsk.wav differ diff --git a/afsk/ax5043.c.bk b/afsk/ax5043.c.bk new file mode 100644 index 00000000..f5b31b91 --- /dev/null +++ b/afsk/ax5043.c.bk @@ -0,0 +1,1162 @@ +/* + * 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_a(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; + printf("1 \n"); + + if (!conf) { + return -PQWS_INVALID_PARAM; + } + + /* Set the initial parameters */ + memset(conf, 0, sizeof(ax5043_conf_t)); + printf("2\n "); + 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; + } + printf("3\n "); + + ret = ax5043_reset_a(conf); + printf("4 \n"); + if (ret) { + return ret; + } + printf("5\n "); + + /* Try first to read the revision register of the AX5043 */ + ret = ax5043_spi_read_8(conf, &revision, AX5043_REG_REV); + printf("6 \n"); + 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; + printf("7 \n"); + ret = ax5043_spi_write_8(conf, AX5043_REG_SCRATCH, val); + printf("8 \n"); + if (ret) { + return ret; + } + + val = 0x0; + printf("9 \n"); + ret = ax5043_spi_read_8(conf, &val, AX5043_REG_SCRATCH); + printf("10 \n"); + if (ret) { + return ret; + } + + if (val != AX5043_SCRATCH_TEST) { + return -PQWS_NO_RF_FOUND; + } + + printf("11 \n"); + ret = ax5043_set_pll_params(conf); + printf("12 \n"); + if (ret) { + return ret; + } + + /* Write the performance register F35 based on the XTAL frequency */ + printf("13 \n"); + if (conf->f_xtaldiv == 1) { + ret = ax5043_spi_write_8(conf, 0xF35, 0x10); + } else { + ret = ax5043_spi_write_8(conf, 0xF35, 0x11); + } + printf("14 \n"); + if (ret) { + return ret; + } + + /* FIFO maximum chunk */ + printf("15 \n"); + ret = ax5043_spi_write_8(conf, AX5043_REG_PKTCHUNKSIZE, + AX5043_PKTCHUNKSIZE_240); + printf("15 \n"); + if (ret) { + return ret; + } + + /* Set RF parameters */ + printf("16 \n"); + ret = ax5043_freqsel(conf, FREQA_MODE); + printf("17 \n"); + 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 + */ + printf("18 \n"); + ret = ax5043_aprs_framing_setup(conf); + printf("19 \n"); + if (ret) { + return ret; + } + + /* Setup TX only related parameters */ + printf("20 \n"); + ret = ax5043_conf_tx_path(conf); + printf("21 \n"); + if (ret) { + return ret; + } + + /* Set an internal copy for the ax5042_wait_for_transmit function */ + __ax5043_conf = conf; + + if (ret) { + return ret; + } + printf("22 \n"); + ax5043_enable_pwramp(conf, AX5043_EXT_PA_DISABLE); + printf("23 \n"); + 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) { + printf("25 \n"); + int ret; + + printf("26 \n"); + ret = ax5043_set_tx_synth(conf); + printf("27 \n"); + if (ret) { + return ret; + } + + printf("28 \n"); + ret = ax5043_set_tx_baud(conf, TX_BAUDRATE); + printf("29 \n"); + if (ret) { + return ret; + } + + // printf("30 \n"); + ret = ax5043_set_tx_freq(conf, TX_FREQ_HZ); + printf("31\n "); + 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 */ + printf("32 \n"); + ret = ax5043_spi_write_8(conf, AX5043_REG_MODCFGA, + AX5043_TX_DIFFERENTIAL); + printf("33 \n"); + if (ret) { + return ret; + } + + /* Set the rest of the performance registers for TX */ + printf("34 \n"); + ret = set_tx_black_magic_regs(conf); + printf("35 \n"); + 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 + printf("36 \n"); + ret = ax5043_spi_write_16(conf, AX5043_REG_TXPWRCOEFFB1, 0x07FF); + printf("37 \n"); + 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.wav b/cw.wav new file mode 100644 index 00000000..276fe223 Binary files /dev/null and b/cw.wav differ diff --git a/cw/cw_main.bk b/cw/cw_main.bk new file mode 100644 index 00000000..28e74bd9 --- /dev/null +++ b/cw/cw_main.bk @@ -0,0 +1,495 @@ +// Sends CubeSatSim telemetry encoded as CW (Morse Code) using AO-7 format +// +// Copyright (c) 2018 Alan Johnston +// +// Portions Copyright (c) 2018 Brandenburg Tech, LLC +// All right reserved. +// +// THIS SOFTWARE IS PROVIDED BY BRANDENBURG TECH, LLC AND CONTRIBUTORS +// ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +// PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BRANDENBURT TECH, LLC +// AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include +#include +#include +#include +#include +//#include +//#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MAX_MESSAGE_LENGTH (197) +#define TRUE 1 +#define FALSE 0 +#define VBATT 15 +#define ADC5 17 +#define ADC6 18 +#define ADC7 19 +#define ADC8 20 +#define TIME 8 +#define UCTEMP 30 +#define UPTIME_SEC 8 +#define A 1 +#define B 2 +#define C 3 +#define D 4 + +#define SENSOR_40 0 +#define SENSOR_41 3 +#define SENSOR_44 6 +#define SENSOR_45 9 +#define SENSOR_4A 12 +#define VOLTAGE 0 +#define CURRENT 1 +#define POWER 2 + +long int timestamp = 0; +extern uint8_t axradio_rxbuffer[]; +void *transmit(void *arg); +int get_message(uint8_t *buffer, int avail); +int lower_digit(int number); +int upper_digit(int number); +int encode_digit(uint8_t *msg, int number); +void config_cw(); +int encode_tlm(uint8_t *buffer, int channel, int val1, int val2, int val3, int val4, int avail); +int encode_header(uint8_t *buffer, int avail); +int add_dash(uint8_t *msg, int number); +int add_dot(uint8_t *msg, int number); +int add_space(uint8_t *msg); +int get_tlm(int tlm[7][5]); +int tempSensor, xPlusSensor, yPlusSensor, zPlusSensor, battCurrentSensor; +extern int config_afsk(); + +int main(void) +{ + uint8_t retVal; + int tlm[7][5]; + int i, j; + for (i = 1; i < 7; i++) { + for (j = 1; j < 5; j++) { + tlm[i][j] = 0; + } + } + tempSensor = wiringPiI2CSetupInterface("/dev/i2c-3", 0x48); + + // Configure SPI bus to AX5043 + setSpiChannel(SPI_CHANNEL); + setSpiSpeed(SPI_SPEED); + initializeSpi(); +// printf("1\n"); + + // if (send_cw_tlm) { +// Send one frame of CW Telem +// Initialize the AX5043 + retVal = axradio_init(); + if (retVal == AXRADIO_ERR_NOCHIP) { + fprintf(stderr, "ERROR: No AX5043 RF chip found\n"); + exit(EXIT_FAILURE); + } + if (retVal != AXRADIO_ERR_NOERROR) { + fprintf(stderr, "ERROR: Unable to initialize AX5043\n"); + exit(EXIT_FAILURE); + } + + printf("INFO: Found and initialized AX5043\n"); + + retVal = mode_tx(); + if (retVal != AXRADIO_ERR_NOERROR) { + fprintf(stderr, "ERROR: Unable to enter TX mode\n"); + exit(EXIT_FAILURE); + } + config_cw(); + + // allocate space for the buffer + static uint8_t packet[MAX_MESSAGE_LENGTH + 1]; + + int channel; // AO-7 telemetry format has 6 channels, 4 sub channels in each + int msg_length; + + while(1) { // loop infinitely + for (channel = 0; channel < 7; channel++) { + + get_tlm(tlm); + if (channel == 0) { + +// start with telemetry header "hi hi" plus a few chars to help CW decoding software sync + msg_length = encode_header(&packet[0], MAX_MESSAGE_LENGTH + 1); + + printf("\nINFO: Sending TLM header\n"); + + } else { + + msg_length = encode_tlm(&packet[0], channel, + tlm[channel][1], tlm[channel][2], tlm[channel][3], tlm[channel][4], + (MAX_MESSAGE_LENGTH + 1)); + + printf("\nINFO: Sending TLM channel %d \n", channel); + } + retVal = transmit_packet(&remoteaddr_tx, packet, (uint16_t)(msg_length)); // send telemetry + if (retVal != AXRADIO_ERR_NOERROR) { + fprintf(stderr, "ERROR: Unable to transmit a packet\n"); + exit(EXIT_FAILURE); + } + } + + usleep(200000); + } +} +// Encodes telemetry header (channel 0) into buffer +// +int encode_header(uint8_t *buffer, int avail) { + + int count = 0; + count += add_space(&buffer[count]); + count += add_space(&buffer[count]); + + count += add_dash(&buffer[count], 1); // c + count += add_dot(&buffer[count], 1); + count += add_dash(&buffer[count], 1); + count += add_dot(&buffer[count], 1); + count += add_space(&buffer[count]); + + count += add_dash(&buffer[count], 2); // q + count += add_dot(&buffer[count], 1); + count += add_dash(&buffer[count], 1); + count += add_space(&buffer[count]); + + count += add_space(&buffer[count]); + + count += add_dot(&buffer[count], 4); // h + count += add_space(&buffer[count]); + + count += add_dot(&buffer[count], 2); // i + count += add_space(&buffer[count]); + + count += add_space(&buffer[count]); + + count += add_dot(&buffer[count], 4); // h + count += add_space(&buffer[count]); + + count += add_dot(&buffer[count], 2); // i + count += add_space(&buffer[count]); + + count += add_space(&buffer[count]); + count += add_space(&buffer[count]); + + if (count > avail) + printf("ERROR: encode_header count > avail \n"); + + return count; +} + +// Encodes one channel of telemetry into buffer +// +int encode_tlm(uint8_t *buffer, int channel, int val1, int val2, int val3, int val4, int avail) { + + int count = 0; + + count += add_space(&buffer[count]); + count += add_space(&buffer[count]); + count += add_space(&buffer[count]); + count += add_space(&buffer[count]); + + count += encode_digit(&buffer[count], channel); // for channel 1, encodes 1aa + count += encode_digit(&buffer[count], upper_digit(val1)); + count += encode_digit(&buffer[count], lower_digit(val1)); + + count += add_space(&buffer[count]); + count += add_space(&buffer[count]); + + count += encode_digit(&buffer[count], channel); // for channel 1, encodes 1bb + count += encode_digit(&buffer[count], upper_digit(val2)); + count += encode_digit(&buffer[count], lower_digit(val2)); + + count += add_space(&buffer[count]); + count += add_space(&buffer[count]); + + count += encode_digit(&buffer[count], channel); // for channel 1, encodes 1cc + count += encode_digit(&buffer[count], upper_digit(val3)); + count += encode_digit(&buffer[count], lower_digit(val3)); + + count += add_space(&buffer[count]); + count += add_space(&buffer[count]); + + count += encode_digit(&buffer[count], channel); // for channel 1, encodes 1dd + count += encode_digit(&buffer[count], upper_digit(val4)); + count += encode_digit(&buffer[count], lower_digit(val4)); + + count += add_space(&buffer[count]); + count += add_space(&buffer[count]); + count += add_space(&buffer[count]); + count += add_space(&buffer[count]); + + //printf("DEBUG count: %d avail: %d \n", count, avail); + if (count > avail) { // make sure not too long + buffer[avail-1] = 0; + count = avail-1; + printf("DEBUG count > avail!\n"); + } +return count; +} +// Encodes a single digit of telemetry into buffer +// +int encode_digit(uint8_t *buffer, int digit) { + int count = 0; + switch(digit) + { + case 0: + count += add_dash(&buffer[count], 5); // 0 + count += add_space(&buffer[count]); + + break; + case 1: + count += add_dot(&buffer[count], 1); // 1 + count += add_dash(&buffer[count], 4); + count += add_space(&buffer[count]); + + break; + case 2: + count += add_dot(&buffer[count], 2); // 2 + count += add_dash(&buffer[count], 3); + count += add_space(&buffer[count]); + + break; + case 3: + count += add_dot(&buffer[count], 3); // 3 + count += add_dash(&buffer[count], 2); + count += add_space(&buffer[count]); + + break; + case 4: + count += add_dot(&buffer[count], 4); // 4 + count += add_dash(&buffer[count], 1); + count += add_space(&buffer[count]); + + break; + case 5: + count += add_dot(&buffer[count], 5); // 5 + count += add_space(&buffer[count]); + + break; + case 6: + count += add_dash(&buffer[count], 1); // 6 + count += add_dot(&buffer[count], 4); + count += add_space(&buffer[count]); + + break; + case 7: + + count += add_dash(&buffer[count], 2); // 7 + count += add_dot(&buffer[count], 3); + count += add_space(&buffer[count]); + + break; + case 8: + count += add_dash(&buffer[count], 3); // 8 + count += add_dot(&buffer[count], 2); + count += add_space(&buffer[count]); + + break; + case 9: + count += add_dash(&buffer[count], 4); // 9 + count += add_dot(&buffer[count], 1); + count += add_space(&buffer[count]); + + break; + default: + printf("ERROR: Not a digit!\n"); + return 0; + } + return count; +} +// Returns lower digit of a number which must be less than 99 +// +int lower_digit(int number) { + + int digit = 0; + if (number < 100) + digit = number - ((int)(number/10) * 10); + else + printf("ERROR: Not a digit in lower_digit!\n"); + return digit; +} +// Returns upper digit of a number which must be less than 99 +// +int upper_digit(int number) { + + int digit = 0; + if (number < 100) + digit = (int)(number/10); + else + printf("ERROR: Not a digit in upper_digit!\n"); + return digit; +} +// Configure radio to send CW which is ASK +// +void config_cw() { + + uint8_t retVal; + +// Configure SPI bus to AX5043 +// setSpiChannel(SPI_CHANNEL); +// setSpiSpeed(SPI_SPEED); +// initializeSpi(); + // printf("1\n"); + + // Initialize the AX5043 + retVal = axradio_init(); +// printf("2\n"); + if (retVal == AXRADIO_ERR_NOCHIP) { + fprintf(stderr, "ERROR: No AX5043 RF chip found\n"); + exit(EXIT_FAILURE); + } + if (retVal != AXRADIO_ERR_NOERROR) { + fprintf(stderr, "ERROR: Unable to initialize AX5043\n"); + exit(EXIT_FAILURE); + } + +// printf("INFO: Found and initialized AX5043\n"); + + retVal = mode_tx(); + if (retVal != AXRADIO_ERR_NOERROR) { + fprintf(stderr, "ERROR: Unable to enter TX mode\n"); + exit(EXIT_FAILURE); + } + +// printf("Register write to clear framing and crc\n"); + ax5043WriteReg(0x12,0); + +// printf("Register write to disable fec\n"); + ax5043WriteReg(0x18,0); + +// printf("Register write \n"); + ax5043WriteReg(0x165,0); + + ax5043WriteReg(0x166,0); + ax5043WriteReg(0x167,0x50); // 0x25); // 0x50); // 0x08); // 0x20); + + ax5043WriteReg(0x161,0); + ax5043WriteReg(0x162,0x20); + +// long txRate; +// txRate = ax5043ReadReg(0x167) + 256 * ax5043ReadReg(0x166) + 65536 * ax5043ReadReg(0x165); +// printf("Tx Rate %x %x %x \n", ax5043ReadReg(0x165), ax5043ReadReg(0x166), ax5043ReadReg(0x167)); +// long fskDev; +// fskDev = ax5043ReadReg(0x163) + 256 * ax5043ReadReg(0x162) + 65536 * ax5043ReadReg(0x161); + + ax5043WriteReg(0x37,(uint8_t)((ax5043ReadReg(0x37) + 4))); // Increase FREQA + +// printf("Tx Rate: %ld FSK Dev: %ld \n", txRate, fskDev); + + ax5043WriteReg(0x10,0); // ASK + +// printf("Modulation: %x \n", (int)ax5043ReadReg(0x10)); +// printf("Frequency A: 0x%x %x %x %x \n",(int)ax5043ReadReg(0x34),(int)ax5043ReadReg(0x35),(int)ax5043ReadReg(0x36),(int)ax5043ReadReg(0x37)); + +/* + int x; + for (x = 0; x < 0x20; x++) + { + printf("Register %x contents: %x\n",x,(int)ax5043ReadReg(x)); + } + + printf("Register Dump complete"); +*/ + return; +} +// Adds a Morse space to the buffer +// +int add_space(uint8_t *msg) { + msg[0] = 0x00; // a space is 8 bits + return 1; +} +// Adds a Morse dash to the buffer +// +int add_dash(uint8_t *msg, int number) { + int j; + int counter = 0; + + for (j=0; j < number; j++) { // a dot is 4 bits, so a dash is 12 bits + msg[counter++] = 0xff; + msg[counter++] = 0x0f; + } + return counter; +} +// Adds a Morse dot to the buffer +// +int add_dot(uint8_t *msg, int number) { + int counter = 0; + int j; + for (j=0; j < number; j++) { // a dot is 4 bits + msg[counter++] = 0x0f; + } + return counter; +} +int get_tlm(int tlm[][5]) { + +// Reading I2C voltage and current sensors + + char cmdbuffer[1000]; + FILE* file = popen("sudo python /home/pi/CubeSatSim/python/readcurrent.py 2>&1", "r"); + fgets(cmdbuffer, 1000, file); + pclose(file); + printf("I2C Sensor data: %s\n", cmdbuffer); + + char ina219[16][20]; // voltage, currents, and power from the INA219 current sensors x4a, x40, x41, x44, and x45. + int i = 0; + char * data2 = strtok (cmdbuffer," "); + + while (data2 != NULL) { + strcpy(ina219[i], data2); + // printf ("ina219[%d]=%s\n",i,ina219[i]); + data2 = strtok (NULL, " "); + i++; + } +// printf("1B: ina219[%d]: %s val: %f \n", SENSOR_40 + CURRENT, ina219[SENSOR_40 + CURRENT], strtof(ina219[SENSOR_40 + CURRENT], NULL)); + + tlm[1][A] = (int)(strtof(ina219[SENSOR_4A + CURRENT], NULL) / 15 + 0.5); // Current of 5V supply to Pi + tlm[1][B] = (int) (99.5 - strtof(ina219[SENSOR_40 + CURRENT], NULL)/10); // +X current [4] + tlm[1][D] = (int) (99.5 - strtof(ina219[SENSOR_41 + CURRENT], NULL)/10); // +Y current [7] + tlm[1][C] = (int) (99.5 - strtof(ina219[SENSOR_44 + CURRENT], NULL)/10); // +Z current [10] (actually -X current, AO-7 didn't have a Z solar panel?) + + tlm[2][B] = 99; + tlm[2][C] = (int)((time(NULL) - timestamp) / 15) % 100; + tlm[2][D] = (int)(50.5 + strtof(ina219[SENSOR_45 + CURRENT], NULL)/10.0); // NiMH Battery current + + tlm[3][A] = (int)((strtof(ina219[SENSOR_45 + VOLTAGE], NULL) * 10) - 65.5); + tlm[3][B] = (int)(strtof(ina219[SENSOR_4A + VOLTAGE], NULL) * 10.0); // 5V supply to Pi + + int tempValue = wiringPiI2CReadReg16(tempSensor, 0); +// printf("Read: %x\n", tempValue); + uint8_t upper = (uint8_t) (tempValue >> 8); + uint8_t lower = (uint8_t) (tempValue & 0xff); + float temp = (float)lower + ((float)upper / 0x100); + + tlm[4][A] = (int)((95.8 - temp)/1.48 + 0.5); + + tlm[6][B] = 0 ; + tlm[6][D] = 49 + rand() % 3; + +// Display tlm + int k, j; + for (k = 1; k < 7; k++) { + for (j = 1; j < 5; j++) { + printf(" %2d ", tlm[k][j]); + } + printf("\n"); + } + return 0; +} diff --git a/cw/cw_main.c b/cw/cw_main.c index ebf219a9..926644c5 100644 --- a/cw/cw_main.c +++ b/cw/cw_main.c @@ -122,7 +122,7 @@ int main(void) int channel; // AO-7 telemetry format has 6 channels, 4 sub channels in each int msg_length; - while(1) { // loop infinitely + //while(1) { // loop infinitely for (channel = 0; channel < 7; channel++) { get_tlm(tlm); @@ -149,7 +149,7 @@ int main(void) } usleep(200000); - } + //} } // Encodes telemetry header (channel 0) into buffer // diff --git a/cw/cw_main.c.bk b/cw/cw_main.c.bk new file mode 100644 index 00000000..8bfb6392 --- /dev/null +++ b/cw/cw_main.c.bk @@ -0,0 +1,498 @@ +// Sends CubeSatSim telemetry encoded as CW (Morse Code) using AO-7 format +// +// Copyright (c) 2018 Alan Johnston +// +// Portions Copyright (c) 2018 Brandenburg Tech, LLC +// All right reserved. +// +// THIS SOFTWARE IS PROVIDED BY BRANDENBURG TECH, LLC AND CONTRIBUTORS +// ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +// PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BRANDENBURT TECH, LLC +// AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include +#include +#include +#include +#include +//#include +//#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MAX_MESSAGE_LENGTH (197) +#define TRUE 1 +#define FALSE 0 +#define VBATT 15 +#define ADC5 17 +#define ADC6 18 +#define ADC7 19 +#define ADC8 20 +#define TIME 8 +#define UCTEMP 30 +#define UPTIME_SEC 8 +#define A 1 +#define B 2 +#define C 3 +#define D 4 + +#define SENSOR_40 0 +#define SENSOR_41 3 +#define SENSOR_44 6 +#define SENSOR_45 9 +#define SENSOR_4A 12 +#define VOLTAGE 0 +#define CURRENT 1 +#define POWER 2 + +long int timestamp = 0; +extern uint8_t axradio_rxbuffer[]; +void *transmit(void *arg); +int get_message(uint8_t *buffer, int avail); +int lower_digit(int number); +int upper_digit(int number); +int encode_digit(uint8_t *msg, int number); +void config_cw(); +int encode_tlm(uint8_t *buffer, int channel, int val1, int val2, int val3, int val4, int avail); +int encode_header(uint8_t *buffer, int avail); +int add_dash(uint8_t *msg, int number); +int add_dot(uint8_t *msg, int number); +int add_space(uint8_t *msg); +int get_tlm(int tlm[7][5]); +int tempSensor, xPlusSensor, yPlusSensor, zPlusSensor, battCurrentSensor; +extern int config_afsk(); + +int main(void) +{ + uint8_t retVal; + int tlm[7][5]; + int i, j; + for (i = 1; i < 7; i++) { + for (j = 1; j < 5; j++) { + tlm[i][j] = 0; + } + } + tempSensor = wiringPiI2CSetupInterface("/dev/i2c-3", 0x48); + + // Configure SPI bus to AX5043 + setSpiChannel(SPI_CHANNEL); + setSpiSpeed(SPI_SPEED); + initializeSpi(); +// printf("1\n"); + + // if (send_cw_tlm) { +// Send one frame of CW Telem +// Initialize the AX5043 + retVal = axradio_init(); + if (retVal == AXRADIO_ERR_NOCHIP) { + fprintf(stderr, "ERROR: No AX5043 RF chip found\n"); + exit(EXIT_FAILURE); + } + if (retVal != AXRADIO_ERR_NOERROR) { + fprintf(stderr, "ERROR: Unable to initialize AX5043\n"); + exit(EXIT_FAILURE); + } + + printf("INFO: Found and initialized AX5043\n"); + + retVal = mode_tx(); + if (retVal != AXRADIO_ERR_NOERROR) { + fprintf(stderr, "ERROR: Unable to enter TX mode\n"); + exit(EXIT_FAILURE); + } + config_cw(); + + // allocate space for the buffer + static uint8_t packet[MAX_MESSAGE_LENGTH + 1]; + + int channel; // AO-7 telemetry format has 6 channels, 4 sub channels in each + int msg_length; + + while(1) { // loop infinitely + for (channel = 0; channel < 7; channel++) { + + get_tlm(tlm); + if (channel == 0) { + +// start with telemetry header "hi hi" plus a few chars to help CW decoding software sync + msg_length = encode_header(&packet[0], MAX_MESSAGE_LENGTH + 1); + + printf("\nINFO: Sending TLM header\n"); + + } else { + + msg_length = encode_tlm(&packet[0], channel, + tlm[channel][1], tlm[channel][2], tlm[channel][3], tlm[channel][4], + (MAX_MESSAGE_LENGTH + 1)); + + printf("\nINFO: Sending TLM channel %d \n", channel); + } + retVal = transmit_packet(&remoteaddr_tx, packet, (uint16_t)(msg_length)); // send telemetry + if (retVal != AXRADIO_ERR_NOERROR) { + fprintf(stderr, "ERROR: Unable to transmit a packet\n"); + exit(EXIT_FAILURE); + } + } + + usleep(200000); + } +} +// Encodes telemetry header (channel 0) into buffer +// +int encode_header(uint8_t *buffer, int avail) { + + int count = 0; + count += add_space(&buffer[count]); + count += add_space(&buffer[count]); + count += add_space(&buffer[count]); + count += add_space(&buffer[count]); + + count += add_dash(&buffer[count], 1); // c + count += add_dot(&buffer[count], 1); + count += add_dash(&buffer[count], 1); + count += add_dot(&buffer[count], 1); + count += add_space(&buffer[count]); + + count += add_dash(&buffer[count], 2); // q + count += add_dot(&buffer[count], 1); + count += add_dash(&buffer[count], 1); + count += add_space(&buffer[count]); + + count += add_space(&buffer[count]); + count += add_space(&buffer[count]); + + count += add_dot(&buffer[count], 4); // h + count += add_space(&buffer[count]); + + count += add_dot(&buffer[count], 2); // i + count += add_space(&buffer[count]); + + count += add_space(&buffer[count]); + count += add_space(&buffer[count]); + + count += add_dot(&buffer[count], 4); // h + count += add_space(&buffer[count]); + + count += add_dot(&buffer[count], 2); // i + count += add_space(&buffer[count]); + + count += add_space(&buffer[count]); + count += add_space(&buffer[count]); + + if (count > avail) + printf("ERROR: encode_header count > avail \n"); + + return count; +} + +// Encodes one channel of telemetry into buffer +// +int encode_tlm(uint8_t *buffer, int channel, int val1, int val2, int val3, int val4, int avail) { + + int count = 0; + + count += add_space(&buffer[count]); + count += add_space(&buffer[count]); + count += add_space(&buffer[count]); + count += add_space(&buffer[count]); + + count += encode_digit(&buffer[count], channel); // for channel 1, encodes 1aa + count += encode_digit(&buffer[count], upper_digit(val1)); + count += encode_digit(&buffer[count], lower_digit(val1)); + + count += add_space(&buffer[count]); + count += add_space(&buffer[count]); + + count += encode_digit(&buffer[count], channel); // for channel 1, encodes 1bb + count += encode_digit(&buffer[count], upper_digit(val2)); + count += encode_digit(&buffer[count], lower_digit(val2)); + + count += add_space(&buffer[count]); + count += add_space(&buffer[count]); + + count += encode_digit(&buffer[count], channel); // for channel 1, encodes 1cc + count += encode_digit(&buffer[count], upper_digit(val3)); + count += encode_digit(&buffer[count], lower_digit(val3)); + + count += add_space(&buffer[count]); + count += add_space(&buffer[count]); + + count += encode_digit(&buffer[count], channel); // for channel 1, encodes 1dd + count += encode_digit(&buffer[count], upper_digit(val4)); + count += encode_digit(&buffer[count], lower_digit(val4)); + + count += add_space(&buffer[count]); + count += add_space(&buffer[count]); + count += add_space(&buffer[count]); + + //printf("DEBUG count: %d avail: %d \n", count, avail); + if (count > avail) { // make sure not too long + buffer[avail-1] = 0; + count = avail-1; + printf("DEBUG count > avail!\n"); + } +return count; +} +// Encodes a single digit of telemetry into buffer +// +int encode_digit(uint8_t *buffer, int digit) { + int count = 0; + switch(digit) + { + case 0: + count += add_dash(&buffer[count], 5); // 0 + count += add_space(&buffer[count]); + + break; + case 1: + count += add_dot(&buffer[count], 1); // 1 + count += add_dash(&buffer[count], 4); + count += add_space(&buffer[count]); + + break; + case 2: + count += add_dot(&buffer[count], 2); // 2 + count += add_dash(&buffer[count], 3); + count += add_space(&buffer[count]); + + break; + case 3: + count += add_dot(&buffer[count], 3); // 3 + count += add_dash(&buffer[count], 2); + count += add_space(&buffer[count]); + + break; + case 4: + count += add_dot(&buffer[count], 4); // 4 + count += add_dash(&buffer[count], 1); + count += add_space(&buffer[count]); + + break; + case 5: + count += add_dot(&buffer[count], 5); // 5 + count += add_space(&buffer[count]); + + break; + case 6: + count += add_dash(&buffer[count], 1); // 6 + count += add_dot(&buffer[count], 4); + count += add_space(&buffer[count]); + + break; + case 7: + + count += add_dash(&buffer[count], 2); // 7 + count += add_dot(&buffer[count], 3); + count += add_space(&buffer[count]); + + break; + case 8: + count += add_dash(&buffer[count], 3); // 8 + count += add_dot(&buffer[count], 2); + count += add_space(&buffer[count]); + + break; + case 9: + count += add_dash(&buffer[count], 4); // 9 + count += add_dot(&buffer[count], 1); + count += add_space(&buffer[count]); + + break; + default: + printf("ERROR: Not a digit!\n"); + return 0; + } + return count; +} +// Returns lower digit of a number which must be less than 99 +// +int lower_digit(int number) { + + int digit = 0; + if (number < 100) + digit = number - ((int)(number/10) * 10); + else + printf("ERROR: Not a digit in lower_digit!\n"); + return digit; +} +// Returns upper digit of a number which must be less than 99 +// +int upper_digit(int number) { + + int digit = 0; + if (number < 100) + digit = (int)(number/10); + else + printf("ERROR: Not a digit in upper_digit!\n"); + return digit; +} +// Configure radio to send CW which is ASK +// +void config_cw() { + + uint8_t retVal; + +// Configure SPI bus to AX5043 +// setSpiChannel(SPI_CHANNEL); +// setSpiSpeed(SPI_SPEED); +// initializeSpi(); + // printf("1\n"); + + // Initialize the AX5043 + retVal = axradio_init(); +// printf("2\n"); + if (retVal == AXRADIO_ERR_NOCHIP) { + fprintf(stderr, "ERROR: No AX5043 RF chip found\n"); + exit(EXIT_FAILURE); + } + if (retVal != AXRADIO_ERR_NOERROR) { + fprintf(stderr, "ERROR: Unable to initialize AX5043\n"); + exit(EXIT_FAILURE); + } + +// printf("INFO: Found and initialized AX5043\n"); + + retVal = mode_tx(); + if (retVal != AXRADIO_ERR_NOERROR) { + fprintf(stderr, "ERROR: Unable to enter TX mode\n"); + exit(EXIT_FAILURE); + } + +// printf("Register write to clear framing and crc\n"); + ax5043WriteReg(0x12,0); + +// printf("Register write to disable fec\n"); + ax5043WriteReg(0x18,0); + +// printf("Register write \n"); + ax5043WriteReg(0x165,0); + + ax5043WriteReg(0x166,0); + ax5043WriteReg(0x167,0x50); // 0x25); // 0x50); // 0x08); // 0x20); + + ax5043WriteReg(0x161,0); + ax5043WriteReg(0x162,0x20); + +// long txRate; +// txRate = ax5043ReadReg(0x167) + 256 * ax5043ReadReg(0x166) + 65536 * ax5043ReadReg(0x165); +// printf("Tx Rate %x %x %x \n", ax5043ReadReg(0x165), ax5043ReadReg(0x166), ax5043ReadReg(0x167)); +// long fskDev; +// fskDev = ax5043ReadReg(0x163) + 256 * ax5043ReadReg(0x162) + 65536 * ax5043ReadReg(0x161); + + ax5043WriteReg(0x37,(uint8_t)((ax5043ReadReg(0x37) + 4))); // Increase FREQA + +// printf("Tx Rate: %ld FSK Dev: %ld \n", txRate, fskDev); + + ax5043WriteReg(0x10,0); // ASK + +// printf("Modulation: %x \n", (int)ax5043ReadReg(0x10)); +// printf("Frequency A: 0x%x %x %x %x \n",(int)ax5043ReadReg(0x34),(int)ax5043ReadReg(0x35),(int)ax5043ReadReg(0x36),(int)ax5043ReadReg(0x37)); + +/* + int x; + for (x = 0; x < 0x20; x++) + { + printf("Register %x contents: %x\n",x,(int)ax5043ReadReg(x)); + } + + printf("Register Dump complete"); +*/ + return; +} +// Adds a Morse space to the buffer +// +int add_space(uint8_t *msg) { + msg[0] = 0x00; // a space is 8 bits + return 1; +} +// Adds a Morse dash to the buffer +// +int add_dash(uint8_t *msg, int number) { + int j; + int counter = 0; + + for (j=0; j < number; j++) { // a dot is 4 bits, so a dash is 12 bits + msg[counter++] = 0xff; + msg[counter++] = 0x0f; + } + return counter; +} +// Adds a Morse dot to the buffer +// +int add_dot(uint8_t *msg, int number) { + int counter = 0; + int j; + for (j=0; j < number; j++) { // a dot is 4 bits + msg[counter++] = 0x0f; + } + return counter; +} +int get_tlm(int tlm[][5]) { + +// Reading I2C voltage and current sensors + + char cmdbuffer[1000]; + FILE* file = popen("sudo python /home/pi/CubeSatSim/python/readcurrent.py 2>&1", "r"); + fgets(cmdbuffer, 1000, file); + pclose(file); + printf("I2C Sensor data: %s\n", cmdbuffer); + + char ina219[16][20]; // voltage, currents, and power from the INA219 current sensors x4a, x40, x41, x44, and x45. + int i = 0; + char * data2 = strtok (cmdbuffer," "); + + while (data2 != NULL) { + strcpy(ina219[i], data2); + // printf ("ina219[%d]=%s\n",i,ina219[i]); + data2 = strtok (NULL, " "); + i++; + } +// printf("1B: ina219[%d]: %s val: %f \n", SENSOR_40 + CURRENT, ina219[SENSOR_40 + CURRENT], strtof(ina219[SENSOR_40 + CURRENT], NULL)); + + tlm[1][A] = (int)(strtof(ina219[SENSOR_4A + CURRENT], NULL) / 15 + 0.5); // Current of 5V supply to Pi + tlm[1][B] = (int) (99.5 - strtof(ina219[SENSOR_40 + CURRENT], NULL)/10); // +X current [4] + tlm[1][D] = (int) (99.5 - strtof(ina219[SENSOR_41 + CURRENT], NULL)/10); // +Y current [7] + tlm[1][C] = (int) (99.5 - strtof(ina219[SENSOR_44 + CURRENT], NULL)/10); // +Z current [10] (actually -X current, AO-7 didn't have a Z solar panel?) + + tlm[2][B] = 99; + tlm[2][C] = (int)((time(NULL) - timestamp) / 15) % 100; + tlm[2][D] = (int)(50.5 + strtof(ina219[SENSOR_45 + CURRENT], NULL)/10.0); // NiMH Battery current + + tlm[3][A] = (int)((strtof(ina219[SENSOR_45 + VOLTAGE], NULL) * 10) - 65.5); + tlm[3][B] = (int)(strtof(ina219[SENSOR_4A + VOLTAGE], NULL) * 10.0); // 5V supply to Pi + + int tempValue = wiringPiI2CReadReg16(tempSensor, 0); +// printf("Read: %x\n", tempValue); + uint8_t upper = (uint8_t) (tempValue >> 8); + uint8_t lower = (uint8_t) (tempValue & 0xff); + float temp = (float)lower + ((float)upper / 0x100); + + tlm[4][A] = (int)((95.8 - temp)/1.48 + 0.5); + + tlm[6][B] = 0 ; + tlm[6][D] = 49 + rand() % 3; + +// Display tlm + int k, j; + for (k = 1; k < 7; k++) { + for (j = 1; j < 5; j++) { + printf(" %2d ", tlm[k][j]); + } + printf("\n"); + } + return 0; +} diff --git a/radio.cw.bk b/radio.cw.bk new file mode 100755 index 00000000..e980f3d5 Binary files /dev/null and b/radio.cw.bk differ diff --git a/radio.cw.bk2 b/radio.cw.bk2 new file mode 100755 index 00000000..e980f3d5 Binary files /dev/null and b/radio.cw.bk2 differ diff --git a/radio.cw.once b/radio.cw.once index efcaf22b..d9aac187 100755 Binary files a/radio.cw.once and b/radio.cw.once differ diff --git a/radio.cw.once.bk b/radio.cw.once.bk new file mode 100755 index 00000000..efcaf22b Binary files /dev/null and b/radio.cw.once.bk differ diff --git a/radioafsk b/radioafsk new file mode 100755 index 00000000..5554eda4 Binary files /dev/null and b/radioafsk differ diff --git a/radiocw b/radiocw new file mode 100755 index 00000000..d9aac187 Binary files /dev/null and b/radiocw differ diff --git a/receive/.cproject b/receive/.cproject deleted file mode 100644 index baaad743..00000000 --- a/receive/.cproject +++ /dev/null @@ -1,116 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/receive/.gitignore b/receive/.gitignore deleted file mode 100644 index 3df573fe..00000000 --- a/receive/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/Debug/ diff --git a/receive/.project b/receive/.project deleted file mode 100644 index e68b8c5c..00000000 --- a/receive/.project +++ /dev/null @@ -1,26 +0,0 @@ - - - receive - - - - - - org.eclipse.cdt.managedbuilder.core.genmakebuilder - clean,full,incremental, - - - - - org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder - full,incremental, - - - - - - org.eclipse.cdt.core.cnature - org.eclipse.cdt.managedbuilder.core.managedBuildNature - org.eclipse.cdt.managedbuilder.core.ScannerConfigNature - - diff --git a/receive/.settings/language.settings.xml b/receive/.settings/language.settings.xml deleted file mode 100644 index 9c8c2c6a..00000000 --- a/receive/.settings/language.settings.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/receive/.settings/org.eclipse.cdt.managedbuilder.core.prefs b/receive/.settings/org.eclipse.cdt.managedbuilder.core.prefs deleted file mode 100644 index 3e369141..00000000 --- a/receive/.settings/org.eclipse.cdt.managedbuilder.core.prefs +++ /dev/null @@ -1,11 +0,0 @@ -eclipse.preferences.version=1 -environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.mingw.exe.debug.1428445818/CPATH/delimiter=; -environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.mingw.exe.debug.1428445818/CPATH/operation=remove -environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.mingw.exe.debug.1428445818/C_INCLUDE_PATH/delimiter=; -environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.mingw.exe.debug.1428445818/C_INCLUDE_PATH/operation=remove -environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.mingw.exe.debug.1428445818/append=true -environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.mingw.exe.debug.1428445818/appendContributed=true -environment/buildEnvironmentLibrary/cdt.managedbuild.config.gnu.mingw.exe.debug.1428445818/LIBRARY_PATH/delimiter=; -environment/buildEnvironmentLibrary/cdt.managedbuild.config.gnu.mingw.exe.debug.1428445818/LIBRARY_PATH/operation=remove -environment/buildEnvironmentLibrary/cdt.managedbuild.config.gnu.mingw.exe.debug.1428445818/append=true -environment/buildEnvironmentLibrary/cdt.managedbuild.config.gnu.mingw.exe.debug.1428445818/appendContributed=true diff --git a/receive/receive_main.c b/receive/receive_main.c deleted file mode 100644 index cab15001..00000000 --- a/receive/receive_main.c +++ /dev/null @@ -1,104 +0,0 @@ -// Copyright (c) 2018 Brandenburg Tech, LLC -// All right reserved. -// -// THIS SOFTWARE IS PROVIDED BY BRANDENBURG TECH, LLC AND CONTRIBUTORS -// ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A -// PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BRANDENBURT TECH, LLC -// AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; -// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR -// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF -// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// Copyright (c) 2007,2008,2009,2010,2011,2012,2013, 2014 AXSEM AG -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// -// 1.Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// 2.Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// 3.Neither the name of AXSEM AG, Duebendorf nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// 4.All advertising materials mentioning features or use of this software -// must display the following acknowledgement: -// This product includes software developed by AXSEM AG and its contributors. -// 5.The usage of this source code is only granted for operation with AX5043 -// and AX8052F143. Porting to other radio or communication devices is -// strictly prohibited. -// -// THIS SOFTWARE IS PROVIDED BY AXSEM AG AND CONTRIBUTORS ``AS IS'' AND ANY -// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL AXSEM AG AND CONTRIBUTORS BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#include -#include -#include -#include -#include -#include -#include -#include - -extern uint8_t axradio_rxbuffer[]; - -int main(void) -{ - uint8_t retVal; - - setSpiChannel(SPI_CHANNEL); - setSpiSpeed(SPI_SPEED); - initializeSpi(); - - retVal = axradio_init(); - if (retVal == AXRADIO_ERR_NOCHIP) { - fprintf(stderr, "ERROR: No AX5043 RF chip found\n"); - exit(EXIT_FAILURE); - } - if (retVal != AXRADIO_ERR_NOERROR) { - fprintf(stderr, "ERROR: Unable to initialize AX5043\n"); - exit(EXIT_FAILURE); - } - - printf("INFO: Found and initialized AX5043\n"); - - retVal = mode_rx(); - if (retVal != AXRADIO_ERR_NOERROR) { - fprintf(stderr, "ERROR: Unable to enter RX mode\n"); - exit(EXIT_FAILURE); - } - - for (;;) { - retVal = receive_packet(); - if (retVal > 0) { - uint8_t counter = 0; - while (retVal-- > 0) { - if (counter > 0 && counter % 16 == 0) { - printf("\n"); - } - printf("%02x ", axradio_rxbuffer[counter++]); - } - printf("\n"); - - } - - usleep(1000000); - } - - return 0; -} - diff --git a/systemd/cubesatsim.service b/systemd/cubesatsim.service index 1f2c17ca..5df4d2b3 100644 --- a/systemd/cubesatsim.service +++ b/systemd/cubesatsim.service @@ -4,7 +4,7 @@ [Service] Type=idle - ExecStart=/home/pi/CubeSatSim/radiocw > /home/pi/CubeSatSim/log.txt 2>&1 + ExecStart=/home/pi/CubeSatSim/demo.sh > /home/pi/CubeSatSim/log.txt 2>&1 [Install] WantedBy=multi-user.target