From 576ad4089e362f614f61bb5ba56fa7c8dd2c99bd Mon Sep 17 00:00:00 2001 From: Savanni D'Gerinel Date: Sat, 2 Jul 2022 17:54:19 -0400 Subject: [PATCH] Proof of concept for a radio transmitter --- display/display.c | 13 +++ display/display.h | 3 + flake.nix | 13 +-- morse_tx/main.c | 139 ----------------------------- prime-tx/main.c | 188 +++++++++++++++++++++++++++++++++++++++ rfm69hcw/rfm.c | 217 +++++++++++++++++++++++++++++++++++++--------- rfm69hcw/rfm.h | 51 +++++++++-- spi/spi.c | 2 +- spi/spi.h | 2 +- 9 files changed, 431 insertions(+), 197 deletions(-) delete mode 100644 morse_tx/main.c create mode 100644 prime-tx/main.c diff --git a/display/display.c b/display/display.c index 0ddcf35..dc88305 100644 --- a/display/display.c +++ b/display/display.c @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with Lum #include #include #include +#include #define ENABLE _BV(5) #define CHARCODE _BV(4) @@ -111,3 +112,15 @@ void display_write_message(display_t *disp, const char *msg) { } } +void display_write_bit_pattern(display_t *disp, const uint8_t pattern) { + char msg[16]; + sprintf(msg, "* "); + for (int i = 7; i >= 0; i--) { + if (pattern & _BV(i)) { + display_write_message(disp, "1"); + } else { + display_write_message(disp, "0"); + } + } +} + diff --git a/display/display.h b/display/display.h index 0cb4314..3b83975 100644 --- a/display/display.h +++ b/display/display.h @@ -45,6 +45,7 @@ Lumeto. If not, see . #define __DISPLAY_H__ #include +#include typedef struct DISPLAY { shift_register_t reg; @@ -64,5 +65,7 @@ void display_set_location(display_t *, size_t, size_t); void display_write_message(display_t *, const char *); +void display_write_bit_pattern(display_t *, const uint8_t); + #endif diff --git a/flake.nix b/flake.nix index ebdbfa8..840b7e2 100644 --- a/flake.nix +++ b/flake.nix @@ -37,16 +37,16 @@ ''; }; - packages."x86_64-linux"."morse-tx" = + packages."x86_64-linux"."prime-tx" = let pkgs = import nixpkgs { system = "x86_64-linux"; }; lib = pkgs.lib; avr = pkgs.pkgsCross.avr.buildPackages; in pkgs.stdenv.mkDerivation rec { - name = "morse-tx"; + name = "prime-tx"; src = ./.; - includes = [ "base" "spi" "morse" "rfm69hcw" ]; + includes = [ "base" "spi" "shift_register" "rfm69hcw" "display" ]; MCU = "atmega32u4"; CHIP_SELECT = "AVR_ATmega32u4"; @@ -57,9 +57,10 @@ buildPhase = '' ${avr.gcc}/bin/avr-gcc ${CFLAGS} ${INCLUDE_DIRS} -o rfm.o -c ${src}/rfm69hcw/rfm.c ${avr.gcc}/bin/avr-gcc ${CFLAGS} ${INCLUDE_DIRS} -o spi.o -c ${src}/spi/spi.c - ${avr.gcc}/bin/avr-gcc ${CFLAGS} ${INCLUDE_DIRS} -o morse.o -c ${src}/morse/morse.c - ${avr.gcc}/bin/avr-gcc ${CFLAGS} ${INCLUDE_DIRS} -o main.o -c ${src}/morse_tx/main.c - ${avr.gcc}/bin/avr-gcc ${CFLAGS} -o main.elf main.o morse.o spi.o rfm.o + ${avr.gcc}/bin/avr-gcc ${CFLAGS} ${INCLUDE_DIRS} -o reg.o -c ${src}/shift_register/shift_register.c + ${avr.gcc}/bin/avr-gcc ${CFLAGS} ${INCLUDE_DIRS} -o display.o -c ${src}/display/display.c + ${avr.gcc}/bin/avr-gcc ${CFLAGS} ${INCLUDE_DIRS} -o main.o -c ${src}/prime-tx/main.c + ${avr.gcc}/bin/avr-gcc ${CFLAGS} -o main.elf main.o display.o spi.o rfm.o reg.o $OBJCOPY -O ihex main.elf main.hex ''; installPhase = '' diff --git a/morse_tx/main.c b/morse_tx/main.c deleted file mode 100644 index ca248ce..0000000 --- a/morse_tx/main.c +++ /dev/null @@ -1,139 +0,0 @@ -#include -#include -#include -#include -#include - -// typedef struct RFM { -// spi_t spi; -// gpio_t irq; -// gpio_t reset; -// } rfm_t; -// -// void rfm_initialize(rfm_t *rfm) { -// spi_initialize(&rfm->spi); -// -// spi_acquire(&rfm->spi); -// spi_transfer_byte(&rfm->spi, 0x37 | _BV(7)); -// spi_transfer_byte(&rfm->spi, 0); -// spi_release(&rfm->spi); -// -// spi_acquire(&rfm->spi); -// spi_transfer_byte(&rfm->spi, 0x38 | _BV(7)); -// spi_transfer_byte(&rfm->spi, 1); -// spi_release(&rfm->spi); -// } -// -// void rfm_power_off(rfm_t *rfm) { -// spi_acquire(&rfm->spi); -// spi_transfer_byte(&rfm->spi, 0x11); -// spi_transfer_byte(&rfm->spi, 0x00); -// spi_release(&rfm->spi); -// } -// -// void rfm_send_data(rfm_t *rfm, uint8_t *data, size_t length) { -// /* Go into standby mode */ -// spi_acquire(&rfm->spi); -// spi_transfer_byte(&rfm->spi, 0x11); -// spi_transfer_byte(&rfm->spi, 0x01); -// spi_release(&rfm->spi); -// -// /* Write data to FIFO */ -// spi_acquire(&rfm->spi); -// spi_transfer_byte(&rfm->spi, 0x10); -// for (size_t i = 0; i < length; i++) { -// spi_transfer_byte(&rfm->spi, data[i]); -// } -// spi_release(&rfm->spi); -// -// /* Go into transmit mode */ -// spi_acquire(&rfm->spi); -// spi_transfer_byte(&rfm->spi, 0x11); -// spi_transfer_byte(&rfm->spi, 0x03); -// spi_release(&rfm->spi); -// -// /* Return to standby mode */ -// spi_acquire(&rfm->spi); -// spi_transfer_byte(&rfm->spi, 0x11); -// spi_transfer_byte(&rfm->spi, 0x01); -// spi_release(&rfm->spi); -// } - -void flash(gpio_t *light, size_t count) { - for (size_t i = 0; i < count; i++) { - set_line(light); - _delay_ms(50); - clear_line(light); - _delay_ms(50); - } -} - -int main(void) { - spi_t spi = (spi_t){ - .clock = { .ddr = &DDRB, .port = &PORTB, .pin = &PINB, .addr = 1 }, - .data_out = { .ddr = &DDRB, .port = &PORTB, .pin = &PINB, .addr = 2 }, - .data_in = { .ddr = &DDRB, .port = &PORTB, .pin = &PINB, .addr = 3 }, - .chip_select = { .ddr = &DDRB, .port = &PORTB, .pin = &PINB, .addr = 4 }, - }; - - rfm_t rfm = (rfm_t){ - .spi = spi, - .irq = { .ddr = &DDRE, .port = &PORTE, .pin = &PINE, .addr = 6 }, - .reset = { .ddr = &DDRD, .port = &PORTD, .pin = &PIND, .addr = 4 }, - }; - - gpio_t light = { .ddr = &DDRC, .port = &PORTC, .addr = 7 }; - gpio_t fifo_full = { .ddr = &DDRB, .port = &PORTB, .addr = 7 }; - gpio_t fifo_empty = { .ddr = &DDRB, .port = &PORTB, .addr = 6 }; - - set_line_direction(&light, LINE_OUT); - set_line_direction(&fifo_full, LINE_OUT); - set_line_direction(&fifo_empty, LINE_OUT); - - - flash(&light, 3); - - rfm_initialize(&rfm); - set_line(&light); - uint8_t status = rfm_status(&rfm); - status & _BV(7) ? set_line(&fifo_full) : clear_line(&fifo_full); - status & _BV(6) ? set_line(&fifo_empty) : clear_line(&fifo_empty); - - /* - spi_acquire(&rfm.spi); - spi_transfer_byte(&rfm.spi, 0x11); - spi_transfer_byte(&rfm.spi, 0x01); - spi_release(&rfm.spi); - - spi_acquire(&rfm.spi); - spi_transfer_byte(&rfm.spi, 0x10); - spi_transfer_byte(&rfm.spi, 1); - spi_transfer_byte(&rfm.spi, 2); - spi_transfer_byte(&rfm.spi, 3); - spi_transfer_byte(&rfm.spi, 5); - spi_transfer_byte(&rfm.spi, 7); - spi_transfer_byte(&rfm.spi, 11); - spi_transfer_byte(&rfm.spi, 13); - spi_release(&rfm.spi); - - status = rfm_status(&rfm); - if (status & _BV(7)) { - clear_line(&light); - } else { - set_line(&light); - } - */ - - /* - uint8_t count[1] = { 0 }; - while(1) { - rfm_send_data(&rfm, count, 1); - count[0]++; - set_line(&light); - _delay_ms(50); - clear_line(&light); - _delay_ms(50); - } - */ - return 0; -} diff --git a/prime-tx/main.c b/prime-tx/main.c new file mode 100644 index 0000000..a2957fd --- /dev/null +++ b/prime-tx/main.c @@ -0,0 +1,188 @@ +#include +#include +#include +#include +#include +#include +#include + +void status(display_t *display, rfm_t *radio) { + op_mode_t mode = rfm_mode(radio); + interrupt_flags_t flags = rfm_interrupts(radio); + + display_clear(display); + + if (mode.listen_on) display_write_message(display, "Listen "); + if (mode.mode == sleep) display_write_message(display, "Sleep"); + if (mode.mode == standby) display_write_message(display, "Standby"); + if (mode.mode == fs) display_write_message(display, "FS"); + if (mode.mode == tx) display_write_message(display, "TX"); + if (mode.mode == rx) display_write_message(display, "RX"); + + display_set_location(display, 1, 0); + if (flags.mode_ready) display_write_message(display, "R "); + if (flags.rx_ready) display_write_message(display, "RX "); + if (flags.tx_ready) display_write_message(display, "TX "); + if (flags.timeout) display_write_message(display, "TO "); + if (flags.auto_mode) display_write_message(display, "AM "); + if (flags.sync_addr_match) display_write_message(display, "SM "); + if (flags.fifo_full) display_write_message(display, "F "); + if (flags.fifo_not_empty) display_write_message(display, "NE "); + if (flags.fifo_level) display_write_message(display, "LE "); + if (flags.fifo_overrun) display_write_message(display, "OR "); + if (flags.packet_sent) display_write_message(display, "PS "); + if (flags.payload_ready) display_write_message(display, "PR"); + if (flags.crc_ok) display_write_message(display, "CRC"); +} + +int main(void) { + display_t display = { + .reg = { + .output = { .ddr = &DDRB, .port = &PORTB, .pin = &PINB, .addr = 7 }, + .shift_clock = { .ddr = &DDRB, .port = &PORTB, .pin = &PINB, .addr = 6 }, + .latch_clock = { .ddr = &DDRB, .port = &PORTB, .pin = &PINB, .addr = 5 }, + }, + }; + + rfm_t radio = (rfm_t){ + .spi = { + .clock = { .ddr = &DDRB, .port = &PORTB, .pin = &PINB, .addr = 1 }, + .data_out = { .ddr = &DDRB, .port = &PORTB, .pin = &PINB, .addr = 2 }, + .data_in = { .ddr = &DDRB, .port = &PORTB, .pin = &PINB, .addr = 3 }, + .chip_select = { .ddr = &DDRB, .port = &PORTB, .pin = &PINB, .addr = 4 }, + }, + .irq = { .ddr = &DDRE, .port = &PORTE, .pin = &PINE, .addr = 6 }, + .reset = { .ddr = &DDRD, .port = &PORTD, .pin = &PIND, .addr = 4 }, + }; + + _delay_ms(15); + display_init(&display); + + rfm_error_e error; + + rfm_init(&radio, (uint8_t [4]){ 0xde, 0xca, 0xfb, 0xad }, 4, &error); + + status(&display, &radio); + _delay_ms(1000); + + rfm_transmit(&radio, (uint8_t [7]){ 1, 2, 3, 5, 7, 11, 13 }, 7); + status(&display, &radio); + + while (1) { + _delay_ms(1000); + status(&display, &radio); + interrupt_flags_t flags = rfm_interrupts(&radio); + + if (flags.packet_sent) { + rfm_standby(&radio); + } + } + + /* + */ + + /* + if (!error) { + display_clear(&display); + display_write_message(&display, "Error detected"); + } else { + while (1) { + status(&display, &radio); + _delay_ms(1000); + + rfm_receive_mode(&radio); + status(&display, &radio); + _delay_ms(1000); + rfm_standby(&radio); + + } + } + */ + + /* + status(&display, &radio); + _delay_ms(1000); + + rfm_set_mode(&display, &radio, (op_mode_t){ .listen_on = true, .mode = standby }); + _delay_ms(1000); + rfm_set_mode(&display, &radio, (op_mode_t){ .listen_on = true, .mode = standby }); + _delay_ms(1000); + */ + + /* + rfm_packet_format(&radio, fixed, 8); + + rfm_set_mode(&display, &radio, (op_mode_t){ .listen_on = false, .mode = rx }); + _delay_ms(1000); + status(&display, &radio); + */ + + + /* + while (1) { + status(&display, &radio); + _delay_ms(1000); + + uint8_t data; + rfm_receive(rfm, &data, 1); + */ + + /* + uint8_t b[8]; + char msg[32]; + status(&display, &radio); + _delay_ms(1000); + + interrupt_flags_t flags = rfm_interrupts(&radio); + + if (flags.fifo_not_empty) { + rfm_receive(&radio, b, 8); + + display_clear(&display); + for (int i = 0; i < 8; i++) { + sprintf(msg, "%x", b[i]); + } + display_write_message(&display, msg); + _delay_ms(1000); + } + */ + // } + + /* + spi_acquire(&rfm.spi); + spi_transfer_byte(&rfm.spi, 0x11); + spi_transfer_byte(&rfm.spi, 0x01); + spi_release(&rfm.spi); + + spi_acquire(&rfm.spi); + spi_transfer_byte(&rfm.spi, 0x10); + spi_transfer_byte(&rfm.spi, 1); + spi_transfer_byte(&rfm.spi, 2); + spi_transfer_byte(&rfm.spi, 3); + spi_transfer_byte(&rfm.spi, 5); + spi_transfer_byte(&rfm.spi, 7); + spi_transfer_byte(&rfm.spi, 11); + spi_transfer_byte(&rfm.spi, 13); + spi_release(&rfm.spi); + + status = rfm_status(&rfm); + if (status & _BV(7)) { + clear_line(&light); + } else { + set_line(&light); + } + */ + + /* + uint8_t count[1] = { 0 }; + while(1) { + rfm_send_data(&rfm, count, 1); + count[0]++; + set_line(&light); + _delay_ms(50); + clear_line(&light); + _delay_ms(50); + } + */ + return 0; +} diff --git a/rfm69hcw/rfm.c b/rfm69hcw/rfm.c index 6600354..2d9ffe8 100644 --- a/rfm69hcw/rfm.c +++ b/rfm69hcw/rfm.c @@ -13,86 +13,193 @@ You should have received a copy of the GNU General Public License along with Lum #include -void rfm_write(rfm_t *rfm, uint8_t reg, uint8_t *data, size_t length) { +#define REG_FIFO 0x00 +#define REG_OP_MODE 0x01 +#define REG_DATA_MODULE 0x02 +#define REG_VERSION 0x10 +#define REG_RSSI_VALUE 0x24 +#define REG_DIO_MAPPING1 0x25 +#define REG_IRQ_FLAGS1 0x27 +#define REG_IRQ_FLAGS2 0x28 +#define REG_SYNC_CONFIG 0x2e +#define REG_SYNC_VALUE1 0x2f +#define REG_PACKET_CONFIG1 0x37 +#define REG_FIFO_THRESH 0x3c +#define REG_TEST_PA1 0x5a +#define REG_TEST_PA2 0x5c + +#define PA1_LOW_POWER 0x55 +#define PA2_LOW_POWER 0x70 + +void _rfm_write(rfm_t *rfm, uint8_t reg, uint8_t *data, size_t length) { spi_acquire(&rfm->spi); - spi_transfer_byte(&rfm->spi, _BV(7) | reg); + spi_transceive(&rfm->spi, _BV(7) | reg); for (size_t i = 0; i < length; i++) { - spi_transfer_byte(&rfm->spi, data[i]); + spi_transceive(&rfm->spi, data[i]); } spi_release(&rfm->spi); } -void rfm_read(rfm_t *rfm, uint8_t reg, uint8_t *data, size_t length) { +void _rfm_read(rfm_t *rfm, uint8_t reg, uint8_t *data, size_t length) { spi_acquire(&rfm->spi); - spi_transfer_byte(&rfm->spi, reg); + spi_transceive(&rfm->spi, reg); for (size_t i = 0; i < length; i++) { - data[i] = spi_transfer_byte(&rfm->spi, 0); + data[i] = spi_transceive(&rfm->spi, 0); } spi_release(&rfm->spi); } -void rfm_initialize(rfm_t *rfm) { +void _rfm_set_low_power(rfm_t *rfm) { + _rfm_write(rfm, REG_TEST_PA1, (uint8_t [1]){ PA1_LOW_POWER }, 1); + _rfm_write(rfm, REG_TEST_PA2, (uint8_t [1]){ PA2_LOW_POWER }, 1); +} + +void rfm_init(rfm_t *rfm, uint8_t *sync_word, size_t length, rfm_error_e *error) { + if (!error) return; + spi_initialize(&rfm->spi); + set_line_direction(&rfm->irq, LINE_IN); + set_line_direction(&rfm->reset, LINE_OUT); + + rfm_reset(rfm); + rfm_sleep(rfm); + + uint8_t version; + _rfm_read(rfm, REG_VERSION, &version, 1); + if (version != 0x24) { + *error = radio_not_found; + return; + } + + rfm_set_mode(rfm, (op_mode_t){ .listen_on = false, .mode = standby }); + _rfm_write(rfm, REG_FIFO_THRESH, (uint8_t [1]){ 0x8f }, 1); + _rfm_set_low_power(rfm); + + _rfm_write(rfm, REG_PACKET_CONFIG1, + (uint8_t [1]){ + _BV(7) /* variable length packets */ + | _BV(6) /* DC whitening */ + | _BV(4) /* CRC on */ + | _BV(1) /* packet filtering requires nodeaddress */ + }, 1); + + _rfm_write(rfm, REG_SYNC_CONFIG, (uint8_t [1]){ _BV(7) | (length << 3) }, 1); + uint8_t word_base = REG_SYNC_VALUE1; + for (int i = 0; i < length; i++) { + _rfm_write(rfm, word_base + i, &sync_word[i], length); + } +} + +void rfm_reset(rfm_t *rfm) { + set_line(&rfm->reset); + _delay_us(100); + clear_line(&rfm->reset); + _delay_us(5); } void rfm_packet_format(rfm_t *rfm, packet_format_e format, size_t length) { switch (format) { case unlimited: - rfm_write(rfm, 0x37, (uint8_t [1]){ 0 }, 1); - rfm_write(rfm, 0x38, (uint8_t [1]){ 0 }, 1); + _rfm_write(rfm, 0x37, (uint8_t [1]){ 0 }, 1); + _rfm_write(rfm, 0x38, (uint8_t [1]){ 0 }, 1); break; case fixed: - rfm_write(rfm, 0x37, (uint8_t [1]){ 0 }, 1); - rfm_write(rfm, 0x38, (uint8_t [1]){ length }, 1); + _rfm_write(rfm, 0x37, (uint8_t [1]){ 0 }, 1); + _rfm_write(rfm, 0x38, (uint8_t [1]){ length }, 1); break; case variable: - rfm_write(rfm, 0x37, (uint8_t [1]){ _BV(7) }, 1); - rfm_write(rfm, 0x38, (uint8_t [1]){ 0 }, 1); + _rfm_write(rfm, 0x37, (uint8_t [1]){ _BV(7) }, 1); + _rfm_write(rfm, 0x38, (uint8_t [1]){ 0 }, 1); break; } } +void rfm_sleep(rfm_t *rfm) { + rfm_set_mode(rfm, (op_mode_t){ .listen_on = false, .mode = sleep }); +} + +void rfm_standby(rfm_t *rfm) { + rfm_set_mode(rfm, (op_mode_t){ .listen_on = false, .mode = standby }); +} + +void rfm_transmit(rfm_t *rfm, uint8_t *data, size_t length) { + rfm_set_mode(rfm, (op_mode_t){ .listen_on = false, .mode = standby }); + _rfm_write(rfm, REG_FIFO, data, length); + _rfm_write(rfm, REG_DIO_MAPPING1, (uint8_t [1]){ 0x00 }, 1); + rfm_set_mode(rfm, (op_mode_t){ .listen_on = false, .mode = tx }); +} + +void rfm_receive_mode(rfm_t *rfm) { + _rfm_write(rfm, REG_DIO_MAPPING1, (uint8_t [1]){ _BV(6) }, 1); + rfm_set_mode(rfm, (op_mode_t){ .listen_on = false, .mode = rx }); +} + +void rfm_receive(rfm_t *rfm, uint8_t *data, size_t length) { + _rfm_write(rfm, REG_DIO_MAPPING1, (uint8_t [1]){ _BV(6) }, 1); + rfm_set_mode(rfm, (op_mode_t){ .listen_on = false, .mode = rx }); + _rfm_read(rfm, 0x00, data, length); +} + uint8_t rfm_temperature(rfm_t *rfm) { uint8_t ready = 0; uint8_t temp; - rfm_write(rfm, 0x4e, (uint8_t [1]){ _BV(3) }, 1); + _rfm_write(rfm, 0x4e, (uint8_t [1]){ _BV(3) }, 1); _delay_ms(1); uint8_t i = 0; while (!(ready & _BV(2)) && i < 10) { - rfm_read(rfm, 0x4e, &ready, 1); + _rfm_read(rfm, 0x4e, &ready, 1); i++; _delay_us(100); } - rfm_read(rfm, 0x4f, &temp, 1); + _rfm_read(rfm, 0x4f, &temp, 1); return temp; } -uint8_t rfm_mode(rfm_t *rfm) { - uint8_t mode_flag; - rfm_read(rfm, 0x01, &mode_flag, 1); - return mode_flag; +op_mode_t rfm_mode(rfm_t *rfm) { + op_mode_t op_mode = { + .listen_on = false, + .mode = sleep, + }; + uint8_t flags; + + _rfm_read(rfm, 0x01, &flags, 1); + if (flags & _BV(6)) op_mode.listen_on = 1; + op_mode.mode = (flags & 0b00011100) >> 2; + + return op_mode; +} + +void rfm_set_mode(rfm_t *rfm, op_mode_t mode) { + op_mode_t current = rfm_mode(rfm); + uint8_t flags = mode.mode << 2; + + if (mode.listen_on) { + flags |= _BV(6); + } else if (current.listen_on) { + flags |= _BV(5); + _rfm_write(rfm, REG_OP_MODE, (uint8_t [1]){ flags }, 1); + + flags = flags & ~_BV(5); + } + + _rfm_write(rfm, REG_OP_MODE, (uint8_t [1]){ flags }, 1); } uint8_t rfm_status(rfm_t *rfm) { uint8_t status_flag; - rfm_read(rfm, 0x28, &status_flag, 1); + _rfm_read(rfm, 0x28, &status_flag, 1); return status_flag; } -void rfm_listen(rfm_t *rfm) { - rfm_write(rfm, 0x01, (uint8_t [1]){ _BV(6) }, 1); - _delay_ms(100); -} - uint32_t rfm_frequency(rfm_t *rfm) { uint8_t frequency_bytes[3]; uint32_t frequency; - rfm_read(rfm, 0x07, &frequency_bytes[2], 1); - rfm_read(rfm, 0x08, &frequency_bytes[1], 1); - rfm_read(rfm, 0x09, &frequency_bytes[0], 1); + _rfm_read(rfm, 0x07, &frequency_bytes[2], 1); + _rfm_read(rfm, 0x08, &frequency_bytes[1], 1); + _rfm_read(rfm, 0x09, &frequency_bytes[0], 1); frequency = frequency_bytes[2]; frequency = frequency << 8; @@ -102,19 +209,43 @@ uint32_t rfm_frequency(rfm_t *rfm) { return frequency * 61; } -uint8_t rfm_set_mode(rfm_t *rfm, mode_e mode) { - uint8_t mode_flags; - rfm_read(rfm, 0x01, &mode_flags, 1); - mode_flags = mode_flags & 0b11100011; - /* - mode_flags += (mode << 2); - rfm_write(rfm, 0x01, &mode_flags, 1); - */ - return mode_flags; -} +interrupt_flags_t rfm_interrupts(rfm_t *rfm) { + uint8_t irq_1; + uint8_t irq_2; + interrupt_flags_t flags = { + .mode_ready = false, + .rx_ready = false, + .tx_ready = false, + .timeout = false, + .auto_mode = false, + .sync_addr_match = false, -uint8_t rfm_irq_1(rfm_t *rfm) { - uint8_t irq; - rfm_read(rfm, 0x27, &irq, 1); - return irq; + .fifo_full = false, + .fifo_not_empty = false, + .fifo_level = false, + .fifo_overrun = false, + .packet_sent = false, + .payload_ready = false, + .crc_ok = false, + }; + + _rfm_read(rfm, REG_IRQ_FLAGS1, &irq_1, 1); + _rfm_read(rfm, REG_IRQ_FLAGS2, &irq_2, 1); + + if (irq_1 & _BV(7)) flags.mode_ready = true; + if (irq_1 & _BV(6)) flags.rx_ready = true; + if (irq_1 & _BV(5)) flags.tx_ready = true; + if (irq_1 & _BV(2)) flags.timeout = true; + if (irq_1 & _BV(1)) flags.auto_mode = true; + if (irq_1 & _BV(0)) flags.sync_addr_match = true; + + if (irq_2 & _BV(7)) flags.fifo_full = true; + if (irq_2 & _BV(6)) flags.fifo_not_empty = true; + if (irq_2 & _BV(5)) flags.fifo_level = true; + if (irq_2 & _BV(4)) flags.fifo_overrun = true; + if (irq_2 & _BV(3)) flags.packet_sent = true; + if (irq_2 & _BV(2)) flags.payload_ready = true; + if (irq_2 & _BV(1)) flags.crc_ok = true; + + return flags; } diff --git a/rfm69hcw/rfm.h b/rfm69hcw/rfm.h index 6243222..d3153d1 100644 --- a/rfm69hcw/rfm.h +++ b/rfm69hcw/rfm.h @@ -15,6 +15,12 @@ You should have received a copy of the GNU General Public License along with Lum #include #include +#include + +typedef enum RFM_ERROR_TYPES { + Ok, + radio_not_found, +} rfm_error_e; typedef struct RFM { spi_t spi; @@ -33,22 +39,53 @@ typedef enum MODE { standby, fs, tx, - rx + rx, + listen } mode_e; -void rfm_initialize(rfm_t *rfm); +/* make mode more of a state machine. define the transitions between those machines. */ +typedef struct MODE_FLAGS { + bool listen_on; + mode_e mode; +} op_mode_t; + +typedef struct INTERRUPT_FLAGS { + bool mode_ready; + bool rx_ready; + bool tx_ready; + bool timeout; + bool auto_mode; + bool sync_addr_match; + + bool fifo_full; + bool fifo_not_empty; + bool fifo_level; + bool fifo_overrun; + bool packet_sent; + bool payload_ready; + bool crc_ok; +} interrupt_flags_t; + +void rfm_init(rfm_t *, uint8_t *, size_t, rfm_error_e *); +void rfm_reset(rfm_t *); + + void rfm_packet_format(rfm_t *rfm, packet_format_e format, size_t length); -void rfm_send_data(rfm_t *rfm, uint8_t *data, size_t length); -void rfm_receive_data(rfm_t *rfm, uint8_t *data, size_t length); +void rfm_sleep(rfm_t *); +void rfm_standby(rfm_t *); +void rfm_receive_mode(rfm_t *); +void rfm_transmit(rfm_t *rfm, uint8_t *data, size_t length); +void rfm_receive(rfm_t *rfm, uint8_t *data, size_t length); + +op_mode_t rfm_mode(rfm_t *rfm); +void rfm_set_mode(rfm_t *rfm, op_mode_t mode); -uint8_t rfm_mode(rfm_t *rfm); uint8_t rfm_status(rfm_t *rfm); uint8_t rfm_temperature(rfm_t *rfm); uint32_t rfm_frequency(rfm_t *rfm); void rfm_listen(rfm_t *rfm); -uint8_t rfm_set_mode(rfm_t *rfm, mode_e mode); -uint8_t rfm_irq_1(rfm_t *rfm); +interrupt_flags_t rfm_interrupts(rfm_t *rfm); #endif diff --git a/spi/spi.c b/spi/spi.c index 00c044d..4bed945 100644 --- a/spi/spi.c +++ b/spi/spi.c @@ -31,7 +31,7 @@ void spi_release(spi_t *spi) { set_line(&spi->chip_select); } -uint8_t spi_transfer_byte(spi_t *spi, uint8_t output) { +uint8_t spi_transceive(spi_t *spi, uint8_t output) { uint8_t input = 0; int input_bit; diff --git a/spi/spi.h b/spi/spi.h index 18af083..e8b6767 100644 --- a/spi/spi.h +++ b/spi/spi.h @@ -27,6 +27,6 @@ typedef struct SPI { void spi_initialize(spi_t *spi); void spi_acquire(spi_t *spi); void spi_release(spi_t *spi); -uint8_t spi_transfer_byte(spi_t *spi, uint8_t output); +uint8_t spi_transceive(spi_t *spi, uint8_t output); #endif