Snapshot the latest version of the prime transmitter and the receiver
This commit is contained in:
parent
ff6a5b3d70
commit
b8494551a4
32
flake.nix
32
flake.nix
|
@ -69,6 +69,38 @@
|
|||
'';
|
||||
};
|
||||
|
||||
packages."x86_64-linux"."radio-rx" =
|
||||
let
|
||||
pkgs = import nixpkgs { system = "x86_64-linux"; };
|
||||
lib = pkgs.lib;
|
||||
avr = pkgs.pkgsCross.avr.buildPackages;
|
||||
in pkgs.stdenv.mkDerivation rec {
|
||||
name = "prime-tx";
|
||||
src = ./.;
|
||||
|
||||
includes = [ "base" "spi" "shift_register" "rfm69hcw" "display" ];
|
||||
|
||||
MCU = "atmega32u4";
|
||||
CHIP_SELECT = "AVR_ATmega32u4";
|
||||
F_CPU = "8000000";
|
||||
CFLAGS = ''-O -finline-functions -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -Wall -Werror -Wstrict-prototypes -DF_CPU=${F_CPU} -std=gnu99 -D__${CHIP_SELECT}__=1 -mmcu=${MCU} -DAVR=1'';
|
||||
INCLUDE_DIRS = lib.concatStringsSep " " (map (dir: "-I${src}/${dir}") includes);
|
||||
|
||||
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 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}/radio-rx/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 = ''
|
||||
mkdir $out
|
||||
cp main.elf main.hex $out
|
||||
'';
|
||||
};
|
||||
|
||||
packages."x86_64-linux"."spi_test" =
|
||||
let
|
||||
pkgs = import nixpkgs { system = "x86_64-linux"; };
|
||||
|
|
|
@ -71,29 +71,23 @@ int main(void) {
|
|||
|
||||
status(&display, &radio, clock);
|
||||
|
||||
int next_transmit = 0;
|
||||
int prime = 0;
|
||||
while (1) {
|
||||
if (clock >= next_transmit) {
|
||||
display_clear(&display);
|
||||
char msg[16];
|
||||
sprintf(msg, "sending %d", primes[prime]);
|
||||
display_write_message(&display, msg);
|
||||
status(&display, &radio, clock);
|
||||
|
||||
op_mode_t mode = rfm_mode(&radio);
|
||||
interrupt_flags_t flags = rfm_interrupts(&radio);
|
||||
if (mode.mode == standby) {
|
||||
rfm_transmit(&radio, &primes[prime], 1);
|
||||
if (primes[prime] == 0) {
|
||||
prime = 0;
|
||||
} else {
|
||||
prime++;
|
||||
}
|
||||
next_transmit = clock + 10;
|
||||
_delay_ms(1000);
|
||||
}
|
||||
status(&display, &radio, clock);
|
||||
interrupt_flags_t flags = rfm_interrupts(&radio);
|
||||
|
||||
if (flags.packet_sent) {
|
||||
} else if (mode.mode == tx && flags.packet_sent) {
|
||||
rfm_standby(&radio);
|
||||
}
|
||||
|
||||
clock++;
|
||||
_delay_ms(1000);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,122 @@
|
|||
#include <avr/io.h>
|
||||
#include <base.h>
|
||||
#include <display.h>
|
||||
#include <rfm.h>
|
||||
#include <spi.h>
|
||||
#include <stdio.h>
|
||||
#include <util/delay.h>
|
||||
|
||||
void status(display_t *display, rfm_t *radio, int clock) {
|
||||
op_mode_t mode = rfm_mode(radio);
|
||||
interrupt_flags_t flags = rfm_interrupts(radio);
|
||||
uint8_t rssi = rfm_rssi(radio);
|
||||
|
||||
display_clear(display);
|
||||
|
||||
/*
|
||||
char clock_str[16];
|
||||
sprintf(clock_str, "%4d ", clock);
|
||||
display_write_message(display, clock_str);
|
||||
*/
|
||||
|
||||
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);
|
||||
|
||||
char msg[16];
|
||||
snprintf(msg, 15, "[-%d] ", rssi / 2);
|
||||
display_write_message(display, msg);
|
||||
|
||||
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);
|
||||
display_clear(&display);
|
||||
|
||||
rfm_error_e error;
|
||||
|
||||
rfm_init(&radio, (uint8_t [4]){ 0xde, 0xca, 0xfb, 0xad }, 4, &error);
|
||||
rfm_listen(&radio);
|
||||
|
||||
if (!error) {
|
||||
display_write_message(&display, "error detected");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
uint8_t word[8];
|
||||
uint8_t sync_length = sync_word(&radio, word);
|
||||
char msg[16];
|
||||
snprintf(msg, 15, "sync: %d", sync_length);
|
||||
display_write_message(&display, msg);
|
||||
display_set_location(&display, 1, 0);
|
||||
|
||||
if (sync_length == 4) {
|
||||
snprintf(msg, 15, ": %x %x %x %x", word[0], word[1], word[2], word[3]);
|
||||
} else {
|
||||
snprintf(msg, 15, "word err");
|
||||
}
|
||||
|
||||
display_write_message(&display, msg);
|
||||
_delay_ms(5000);
|
||||
*/
|
||||
|
||||
char msg[16];
|
||||
uint32_t frequency = rfm_frequency(&radio);
|
||||
snprintf(msg, 15, "F: %ld", frequency);
|
||||
display_write_message(&display, msg);
|
||||
_delay_ms(5000);
|
||||
|
||||
while(1) {
|
||||
// char msg[16];
|
||||
// uint8_t packet[66];
|
||||
// uint8_t length;
|
||||
// display_clear(&display);
|
||||
|
||||
// if (length > 0) {
|
||||
// snprintf(msg, 15, "%d ", packet[0]);
|
||||
// display_write_message(&display, msg);
|
||||
// _delay_ms(1000);
|
||||
// }
|
||||
status(&display, &radio, 0);
|
||||
_delay_ms(1000);
|
||||
}
|
||||
}
|
|
@ -12,15 +12,18 @@ You should have received a copy of the GNU General Public License along with Lum
|
|||
|
||||
|
||||
#include <rfm.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#define REG_FIFO 0x00
|
||||
#define REG_OP_MODE 0x01
|
||||
#define REG_DATA_MODULE 0x02
|
||||
#define REG_DATA_MODUL 0x02
|
||||
#define REG_VERSION 0x10
|
||||
#define REG_RSSI_CONFIG 0x23
|
||||
#define REG_RSSI_VALUE 0x24
|
||||
#define REG_DIO_MAPPING1 0x25
|
||||
#define REG_IRQ_FLAGS1 0x27
|
||||
#define REG_IRQ_FLAGS2 0x28
|
||||
#define REG_RSSI_THRESH 0x29
|
||||
#define REG_SYNC_CONFIG 0x2e
|
||||
#define REG_SYNC_VALUE1 0x2f
|
||||
#define REG_PACKET_CONFIG1 0x37
|
||||
|
@ -29,7 +32,9 @@ You should have received a copy of the GNU General Public License along with Lum
|
|||
#define REG_TEST_PA2 0x5c
|
||||
|
||||
#define PA1_LOW_POWER 0x55
|
||||
#define PA1_HIGH_POWER 0x5D
|
||||
#define PA2_LOW_POWER 0x70
|
||||
#define PA2_HIGH_POWER 0x7C
|
||||
|
||||
void _rfm_write(rfm_t *rfm, uint8_t reg, uint8_t *data, size_t length) {
|
||||
spi_acquire(&rfm->spi);
|
||||
|
@ -54,6 +59,11 @@ void _rfm_set_low_power(rfm_t *rfm) {
|
|||
_rfm_write(rfm, REG_TEST_PA2, (uint8_t [1]){ PA2_LOW_POWER }, 1);
|
||||
}
|
||||
|
||||
void _rfm_set_high_power(rfm_t *rfm) {
|
||||
_rfm_write(rfm, REG_TEST_PA1, (uint8_t [1]){ PA1_HIGH_POWER }, 1);
|
||||
_rfm_write(rfm, REG_TEST_PA2, (uint8_t [1]){ PA2_HIGH_POWER }, 1);
|
||||
}
|
||||
|
||||
void rfm_init(rfm_t *rfm, uint8_t *sync_word, size_t length, rfm_error_e *error) {
|
||||
if (!error) return;
|
||||
|
||||
|
@ -72,7 +82,11 @@ void rfm_init(rfm_t *rfm, uint8_t *sync_word, size_t length, rfm_error_e *error)
|
|||
}
|
||||
|
||||
rfm_set_mode(rfm, (op_mode_t){ .listen_on = false, .mode = standby });
|
||||
|
||||
_rfm_write(rfm, REG_DATA_MODUL, (uint8_t [1]){ _BV(3) }, 1);
|
||||
|
||||
_rfm_write(rfm, REG_FIFO_THRESH, (uint8_t [1]){ 0x8f }, 1);
|
||||
_rfm_write(rfm, REG_RSSI_THRESH, (uint8_t [1]){ 0xe4 }, 1);
|
||||
_rfm_set_low_power(rfm);
|
||||
|
||||
_rfm_write(rfm, REG_PACKET_CONFIG1,
|
||||
|
@ -80,16 +94,29 @@ void rfm_init(rfm_t *rfm, uint8_t *sync_word, size_t length, rfm_error_e *error)
|
|||
_BV(7) /* variable length packets */
|
||||
| _BV(6) /* DC whitening */
|
||||
| _BV(4) /* CRC on */
|
||||
| _BV(1) /* packet filtering requires nodeaddress */
|
||||
| _BV(0) /* packet filtering does not require node address */
|
||||
}, 1);
|
||||
|
||||
_rfm_write(rfm, REG_SYNC_CONFIG, (uint8_t [1]){ _BV(7) | (length << 3) }, 1);
|
||||
_rfm_write(rfm, REG_SYNC_CONFIG, (uint8_t [1]){ _BV(7) | (length << 2) }, 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);
|
||||
_rfm_write(rfm, word_base + i, &sync_word[i], 1);
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t sync_word(rfm_t *rfm, uint8_t sync_word[8]) {
|
||||
uint8_t length;
|
||||
|
||||
_rfm_read(rfm, REG_SYNC_CONFIG, &length, 1);
|
||||
length = (length >> 2) & 0b00000111;
|
||||
uint8_t word_base = REG_SYNC_VALUE1;
|
||||
for (int i = 0; i < length; i++) {
|
||||
_rfm_read(rfm, word_base + i, &sync_word[i], 1);
|
||||
}
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
void rfm_reset(rfm_t *rfm) {
|
||||
set_line(&rfm->reset);
|
||||
_delay_us(100);
|
||||
|
@ -122,8 +149,13 @@ void rfm_standby(rfm_t *rfm) {
|
|||
rfm_set_mode(rfm, (op_mode_t){ .listen_on = false, .mode = standby });
|
||||
}
|
||||
|
||||
void rfm_listen(rfm_t *rfm) {
|
||||
rfm_set_mode(rfm, (op_mode_t){ .listen_on = true, .mode = standby });
|
||||
}
|
||||
|
||||
void rfm_transmit(rfm_t *rfm, uint8_t *data, uint8_t length) {
|
||||
rfm_set_mode(rfm, (op_mode_t){ .listen_on = false, .mode = standby });
|
||||
_rfm_set_low_power(rfm);
|
||||
_rfm_write(rfm, REG_FIFO, &length, 1);
|
||||
_rfm_write(rfm, REG_FIFO, data, length);
|
||||
_rfm_write(rfm, REG_DIO_MAPPING1, (uint8_t [1]){ 0x00 }, 1);
|
||||
|
@ -135,10 +167,21 @@ void rfm_receive_mode(rfm_t *rfm) {
|
|||
rfm_set_mode(rfm, (op_mode_t){ .listen_on = false, .mode = rx });
|
||||
}
|
||||
|
||||
void rfm_receive(rfm_t *rfm, uint8_t *data, size_t length) {
|
||||
void rfm_receive(display_t *display, rfm_t *rfm, uint8_t data[66], uint8_t *length) {
|
||||
display_clear(display);
|
||||
|
||||
_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);
|
||||
_rfm_read(rfm, REG_FIFO, length, 1);
|
||||
|
||||
char msg[16];
|
||||
sprintf(msg, "length: %d", *length);
|
||||
display_write_message(display, msg);
|
||||
_delay_ms(1000);
|
||||
|
||||
if (*length > 0) {
|
||||
_rfm_read(rfm, 0x00, data, *length);
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t rfm_temperature(rfm_t *rfm) {
|
||||
|
@ -250,3 +293,20 @@ interrupt_flags_t rfm_interrupts(rfm_t *rfm) {
|
|||
|
||||
return flags;
|
||||
}
|
||||
|
||||
uint8_t rfm_rssi(rfm_t *rfm) {
|
||||
uint8_t rssi_reg;
|
||||
uint8_t rssi_value;
|
||||
|
||||
_rfm_write(rfm, REG_RSSI_CONFIG, (uint8_t [1]){ _BV(0) }, 1);
|
||||
|
||||
while(!(rssi_reg & _BV(1))) {
|
||||
_rfm_read(rfm, REG_RSSI_CONFIG, &rssi_reg, 1);
|
||||
}
|
||||
|
||||
_rfm_read(rfm, REG_RSSI_VALUE, &rssi_value, 1);
|
||||
|
||||
return rssi_value;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@ You should have received a copy of the GNU General Public License along with Lum
|
|||
#include <base.h>
|
||||
#include <spi.h>
|
||||
#include <stdbool.h>
|
||||
#include <display.h>
|
||||
|
||||
typedef enum RFM_ERROR_TYPES {
|
||||
Ok,
|
||||
|
@ -67,16 +68,16 @@ typedef struct INTERRUPT_FLAGS {
|
|||
} interrupt_flags_t;
|
||||
|
||||
void rfm_init(rfm_t *, uint8_t *, size_t, rfm_error_e *);
|
||||
uint8_t sync_word(rfm_t *rfm, uint8_t sync_word[8]);
|
||||
void rfm_reset(rfm_t *);
|
||||
|
||||
|
||||
void rfm_packet_format(rfm_t *rfm, packet_format_e format, 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, uint8_t length);
|
||||
void rfm_receive(rfm_t *rfm, uint8_t *data, size_t length);
|
||||
void rfm_receive(display_t *display, rfm_t *rfm, uint8_t data[66], uint8_t *length);
|
||||
|
||||
op_mode_t rfm_mode(rfm_t *rfm);
|
||||
void rfm_set_mode(rfm_t *rfm, op_mode_t mode);
|
||||
|
@ -88,4 +89,6 @@ uint32_t rfm_frequency(rfm_t *rfm);
|
|||
void rfm_listen(rfm_t *rfm);
|
||||
interrupt_flags_t rfm_interrupts(rfm_t *rfm);
|
||||
|
||||
uint8_t rfm_rssi(rfm_t *rfm);
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue