Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dp4d #135

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open

Dp4d #135

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions rflib/bfsk.c
Original file line number Diff line number Diff line change
@@ -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)
Expand Down Expand Up @@ -44,7 +44,7 @@ static void receive() {
}
}

//# MENU BPSK
//# MENU BFSK
void bfsk_menu() {
lcdClear();
lcdPrintln("ENTER to go back");
Expand Down
108 changes: 108 additions & 0 deletions rflib/dp4d-host/readdp4d.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdint.h>
#include <termio.h>
#include <fcntl.h>
#include <err.h>
#include <linux/serial.h>
#include <sys/time.h>
#include <sys/types.h>

#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 <ttydev>\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);
}
}
}
}
130 changes: 130 additions & 0 deletions rflib/dp4d.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
#include <rad1olib/setup.h>
#include <r0ketlib/display.h>
#include <r0ketlib/print.h>
#include <r0ketlib/itoa.h>
#include <r0ketlib/keyin.h>
#include <r0ketlib/menu.h>
#include <r0ketlib/select.h>
#include <r0ketlib/idle.h>
#include <r0ketlib/config.h>

#include <rad1olib/pins.h>

#include <rad1olib/systick.h>

#include <libopencm3/cm3/systick.h>

#include "../rflib/rflib_m0.h"

#include <lpcapi/cdc/cdc_main.h>
#include <lpcapi/cdc/cdc_vcom.h>

#include <string.h>
#include <stdlib.h>

#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;
}
19 changes: 19 additions & 0 deletions rflib/dp4d.h
Original file line number Diff line number Diff line change
@@ -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
120 changes: 120 additions & 0 deletions rflib/m4ster.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
#include <rad1olib/setup.h>
#include <r0ketlib/display.h>
#include <r0ketlib/print.h>
#include <r0ketlib/itoa.h>
#include <r0ketlib/keyin.h>
#include <r0ketlib/menu.h>
#include <r0ketlib/select.h>
#include <r0ketlib/idle.h>
#include <r0ketlib/config.h>

#include <rad1olib/pins.h>

#include <rad1olib/systick.h>

#include <libopencm3/cm3/systick.h>

#include "../rflib/rflib_m0.h"

#include <lpcapi/cdc/cdc_main.h>
#include <lpcapi/cdc/cdc_vcom.h>

#include <string.h>
#include <stdlib.h>

#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<MAX_CLIENTS; i++) {
/* Poll notice: */
pkg.version = 0x49;
pkg.id = clients[i].id;
pkg.x = 0xFFFF/100 * 10; // 10% probability of client answer (0x28F5C28=0xFFFFFFFF/100)
TOGGLE(LED3);
rflib_bfsk_transmit((uint8_t*)&pkg, sizeof(pkg), true);
/* wait for client reply: */
delayNop(6*40000); // about 6ms?
int pkg_len = rflib_bfsk_get_packet((uint8_t*)&pkg, sizeof(pkg));
if(pkg_len == sizeof(pkg)) {
/* handle client reply */
if(pkg.version != 0x49) continue;
pkg.version = 0;
if(clients[i].id == 0) {
clients[i].id = pkg.id;
pkg.version = 1;
}
clients[i].lifetime = CLIENT_LIFETIME;
cdc_send((uint8_t*)&pkg, sizeof(pkg));
} else {
/* otherwise check for client kickout timer */
if(clients[i].id != 0) {
if(clients[i].lifetime == 0) {
pkg.version = 2;
pkg.id = clients[i].id;
cdc_send((uint8_t*)&pkg, sizeof(pkg));
clients[i].id = 0;
} else {
clients[i].lifetime--;
}
}
}
}
}
}
Loading