diff --git a/rflib/bfsk.c b/rflib/bfsk.c index 6dadc552..4e7aaa05 100644 --- a/rflib/bfsk.c +++ b/rflib/bfsk.c @@ -1,4 +1,4 @@ -/* BPSK RX/TX +/* BFSK RX/TX * * Send/Receive BFSK transmissions using the directional pad * (predefined strings) or via USB/CDC (whatever you want) @@ -44,7 +44,7 @@ static void receive() { } } -//# MENU BPSK +//# MENU BFSK void bfsk_menu() { lcdClear(); lcdPrintln("ENTER to go back"); diff --git a/rflib/dp4d-host/readdp4d.c b/rflib/dp4d-host/readdp4d.c new file mode 100644 index 00000000..17a1983b --- /dev/null +++ b/rflib/dp4d-host/readdp4d.c @@ -0,0 +1,108 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../dp4d.h" + +static int rate_to_constant(int baudrate) { +#define B(x) case x: return B##x + switch(baudrate) { + B(50); B(75); B(110); B(134); B(150); + B(200); B(300); B(600); B(1200); B(1800); + B(2400); B(4800); B(9600); B(19200); B(38400); + B(57600); B(115200); B(230400); B(460800); B(500000); + B(576000); B(921600); B(1000000);B(1152000);B(1500000); + B(4000000); + default: return 0; + } +#undef B +} + +/* Open serial port in raw mode, with custom baudrate if necessary */ +int serial_open(const char *device, int rate) +{ + struct termios options; + struct serial_struct serinfo; + int fd; + int speed = 0; + + /* Open and configure serial port */ + if ((fd = open(device,O_RDWR|O_NOCTTY)) == -1) + return -1; + + speed = rate_to_constant(rate); + + if (speed == 0) { + /* Custom divisor */ + serinfo.reserved_char[0] = 0; + if (ioctl(fd, TIOCGSERIAL, &serinfo) < 0) + return -1; + serinfo.flags &= ~ASYNC_SPD_MASK; + serinfo.flags |= ASYNC_SPD_CUST; + serinfo.custom_divisor = (serinfo.baud_base + (rate / 2)) / rate; + fprintf(stderr, "setting custom divisor %d for baud_base %d\n", serinfo.custom_divisor, serinfo.baud_base); + if (serinfo.custom_divisor < 1) + serinfo.custom_divisor = 1; + if (ioctl(fd, TIOCSSERIAL, &serinfo) < 0) + return -1; + if (ioctl(fd, TIOCGSERIAL, &serinfo) < 0) + return -1; + if (serinfo.custom_divisor * rate != serinfo.baud_base) { + warnx("actual baudrate is %d / %d = %f", + serinfo.baud_base, serinfo.custom_divisor, + (float)serinfo.baud_base / serinfo.custom_divisor); + } + } + + fcntl(fd, F_SETFL, 0); + tcgetattr(fd, &options); + cfsetispeed(&options, speed ?: B38400); + cfsetospeed(&options, speed ?: B38400); + cfmakeraw(&options); + options.c_cflag |= (CLOCAL | CREAD); + options.c_cflag &= ~CRTSCTS; + if (tcsetattr(fd, TCSANOW, &options) != 0) + return -1; + + return fd; +} + +int main(int argc, char *argv[]) { + if(argc < 2) { + fprintf(stderr, "call this like\n%s \n", argv[0]); + return -1; + } + int fd = serial_open(argv[1], 4000000); + if(fd == -1) { + fprintf(stderr, "error opening serial device, exiting.\n"); + return -1; + } + + write(fd, "GO", 2); + + ssize_t r; + dp4d_pkg pkg; + while(1) { + r = read(fd, (void*)&pkg, sizeof(pkg)); + if(r == -1) { + perror(NULL); + return -1; + } + if(r == sizeof(pkg)) { + if(pkg.version == 0) { + fprintf(stdout, "Data: ID=%08x x=%d y=%d btn=%d\n", pkg.id, pkg.x, pkg.y, pkg.button); + } else if(pkg.version == 1) { + fprintf(stdout, "New: ID=%08x x=%d y=%d btn=%d\n", pkg.id, pkg.x, pkg.y, pkg.button); + } else if(pkg.version == 2) { + fprintf(stdout, "Gone: ID=%08x\n", pkg.id); + } + } + } +} diff --git a/rflib/dp4d.c b/rflib/dp4d.c new file mode 100644 index 00000000..86c46a44 --- /dev/null +++ b/rflib/dp4d.c @@ -0,0 +1,130 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include + +#include "../rflib/rflib_m0.h" + +#include +#include + +#include +#include + +#include "dp4d.h" + +// default to 2399 MHz +#define FREQSTART 2399000000 + +//# MENU dp4d +void dp4d() { + dp4d_pkg pkg; + + uint16_t x = 0; + uint16_t y = 0; + uint32_t regcount = 0; + uint16_t btn = 0; + uint32_t id = 0; + + cpu_clock_set(204); + + rflib_init(); + rflib_set_freq(FREQSTART); + // first, we let the frequency detector + // work on some noise or stuff, and use that to initialize + // the pseudorandom number generator + rflib_set_rxsamplerate(1000000); + rflib_set_rxdecimation(2); + rflib_set_rxbandwidth(1750000); + rflib_freq_receive(); + int seed_bits = 0; + int rand_seed = 0; + while(seed_bits < 32) { + int16_t freq = 0; + if(rflib_get_data(&freq, 2) > 0) { + rand_seed |= ((freq & 0x100) > 0 ? 1 : 0); + rand_seed <<= 1; + seed_bits++; + } + } + rflib_standby(); + srand(rand_seed); + id = rand(); + + lcdPrintln("your dp4d ID:"); + lcdPrintln(IntToStr(id, 8, F_HEX)); + rflib_lcdDisplay(); + + systick_interrupt_disable(); + + rflib_bfsk_init(); + rflib_bfsk_receive(); + + while(1) { + switch (getInputRaw()) { + case BTN_UP: + y++; + break; + case BTN_DOWN: + y--; + break; + case BTN_RIGHT: + x++; + break; + case BTN_LEFT: + x--; + break; + case BTN_ENTER: + btn = 0xFFF; + break; + } + + // Poll for BFSK packets + int pkg_len = rflib_bfsk_get_packet((uint8_t*)&pkg, sizeof(pkg)); + if(pkg_len == sizeof(pkg)) { + TOGGLE(LED3); + delayNop(10000); // about 250us? + if(pkg.version != 0x49) goto cont; + if(pkg.id == id) { + // we're queried, answer as fast as possible + ON(LED4); + regcount = 3000; + pkg.x = x; + pkg.y = y; + pkg.button = btn>>4; + rflib_bfsk_transmit((uint8_t*)&pkg, sizeof(pkg), true); + } + // if not registered, answer to queries for new dp4d clients + if((regcount == 0) && (pkg.id == 0) && (pkg.x > (rand()>>16))) { + pkg.id = id; + pkg.x = x; + pkg.y = y; + pkg.button = 0; + regcount = 500; // only try once every sec + rflib_bfsk_transmit((uint8_t*)&pkg, sizeof(pkg), true); + } + } +cont: + delayNop(80000); // about 2ms? + if(btn > 0) btn--; + if(regcount > 0) { + regcount--; + } else { + OFF(LED4); + } + } + + rflib_shutdown(); + return; +} diff --git a/rflib/dp4d.h b/rflib/dp4d.h new file mode 100644 index 00000000..0a792975 --- /dev/null +++ b/rflib/dp4d.h @@ -0,0 +1,19 @@ +#ifndef _DP4D_H +#define _DP4D_H + +struct dp4d_pkg_s { + uint8_t version; + uint8_t button; + uint16_t x; + uint16_t y; + uint32_t id; +} __attribute__((packed)); +typedef struct dp4d_pkg_s dp4d_pkg; + +struct dp4d_client_s { + uint32_t id; + uint32_t lifetime; +}; +typedef struct dp4d_client_s dp4d_client; + +#endif // _DP4D_H diff --git a/rflib/m4ster.c b/rflib/m4ster.c new file mode 100644 index 00000000..e76e62e8 --- /dev/null +++ b/rflib/m4ster.c @@ -0,0 +1,120 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include + +#include "../rflib/rflib_m0.h" + +#include +#include + +#include +#include + +#include "dp4d.h" + +// default to 2399 MHz +#define FREQSTART 2399000000 + +static void hex2(uint8_t* buf, uint32_t v, int pos) { + if(pos == 8) return; + const int d = (v & 0xF0000000) >> 28; + *buf = (d > 9) ? 'A'-10+d : '0'+d; + hex2(buf+1, v<<4, pos+1); +} + +static void cdc_send(uint8_t* msg, int len) { + if(vcom_connected()) vcom_write(msg, len); +} + +#define MAX_CLIENTS 10 +#define CLIENT_LIFETIME 50 +//# MENU m4ster +void m4ster() { + uint16_t x = 0; + uint16_t y = 0; + uint32_t regcount = 0; + uint32_t btntime = 0; + uint32_t id = 0; + uint16_t free_slot = 0; + static dp4d_pkg pkg; + static dp4d_client clients[MAX_CLIENTS]; + + memset(clients, 0, MAX_CLIENTS*sizeof(dp4d_client)); + + cpu_clock_set(204); + + rflib_init(); + rflib_set_freq(FREQSTART); + + lcdPrintln("send USB/CDC"); + lcdPrintln("initialization"); + lcdPrintln("now..."); + rflib_lcdDisplay(); + + getInputWaitRelease(); + systick_interrupt_disable(); + + CDCenable(); + + bool have_init = false; + while(!have_init) { + if(vcom_connected()) { + /* check if we got data from USB-CDC, check sequence, if so. */ + uint8_t buf[2]; + uint32_t read = vcom_bread(buf, 2); + if(read == 2 && buf[0] == 'G' && buf[1] == 'O') have_init = true; + } + } + + rflib_bfsk_init(); + rflib_bfsk_receive(); + + while(1) { + for(int i=0; i