Merge branch 'master' of github.com:r0ket/r0ket

This commit is contained in:
schneider 2011-12-16 15:56:11 +01:00
commit ae1fd15ad9
58 changed files with 2379 additions and 1747 deletions

1
.gitignore vendored
View File

@ -3,3 +3,4 @@
*.a
*.swp
release
*.pyc

18
firmware/BRIDGE-PROTOCOL Normal file
View File

@ -0,0 +1,18 @@
Receiving:
r->h: \1<packet data>\0
Sending:
h->r: \1<packet data>\0
r->h: \2\0
Settings:
h->r:\3<TXMAC>\0
r->h: \2\0
h->r:\4<RXMAX>\0
r->h: \2\0
h->r:\5<CHANNEL>\0
r->h: \2\0
h->r:\6<MACLEN>\0
r->h: \2\0

View File

@ -1,7 +1,7 @@
#ifndef _SECRETS_
#define _SECRETS_
#define ENCRYPT_L0DABLE 1
#undef ENCRYPT_L0DABLE 1
static uint32_t const meshkey[4] = {
0xafbbcb26, 0x39108427, 0x455ef5e5, 0x51b482d2

View File

@ -82,7 +82,7 @@ void tick_default(void) {
gpioSetValue (RB_LED0, 1);
gpioSetValue (RB_LED2, 1);
posleds = 1;
}else if( posleds = 1 ){
}else if( posleds ){
gpioSetValue (RB_LED0, 0);
gpioSetValue (RB_LED2, 0);
}

View File

@ -0,0 +1,38 @@
#include <sysinit.h>
#include "basic/basic.h"
#include "lcd/print.h"
#include "lcd/display.h"
#include "filesystem/ff.h"
#include <string.h>
/**************************************************************************/
void readcfg(void) {
readConfig();
};
void savecfg(void){
saveConfig();
};
void applycfg(void){
applyConfig();
};
void show(void){
lcdClear();
lcdPrint("time:"); lcdPrintInt(globalconfig.time); lcdNl();
lcdPrint("btrig:"); lcdPrintInt(globalconfig.backlighttrigger); lcdNl();
lcdPrint("bval:"); lcdPrintInt(globalconfig.backlightvalue); lcdNl();
lcdPrint("lcd:"); lcdPrintInt(globalconfig.lcdstate); lcdNl();
lcdPrint("priv:"); lcdPrintInt(globalconfig.privacy); lcdNl();
lcdRefresh();
};
void lcdmirror(void){
lcdToggleFlag(LCD_MIRRORX);
};

View File

@ -0,0 +1,272 @@
#include <sysinit.h>
#include "basic/basic.h"
#include "basic/byteorder.h"
#include "lcd/lcd.h"
#include "lcd/print.h"
#include "funk/nrf24l01p.h"
#include "usbcdc/usb.h"
#include "usbcdc/usbcore.h"
#include "usbcdc/usbhw.h"
#include "usbcdc/cdcuser.h"
#include "usbcdc/cdc_buf.h"
#include "usbcdc/util.h"
#include <string.h>
#define REMOTE_CHANNEL 91
#define REMOTE_MAC "REM0T"
#if CFG_USBMSC
#error "MSC is defined"
#endif
#if !CFG_USBCDC
#error "CDC is not defined"
#endif
/**************************************************************************/
#include "SECRETS"
void r_init(void){
nrf_init();
struct NRF_CFG config = {
.channel= REMOTE_CHANNEL,
.txmac= REMOTE_MAC,
.nrmacs=1,
.mac0= REMOTE_MAC,
.maclen ="\x10",
};
nrf_config_set(&config);
};
void s_init(void){
usbCDCInit();
nrf_init();
struct NRF_CFG config = {
.channel= REMOTE_CHANNEL,
.txmac= REMOTE_MAC,
.nrmacs=1,
.mac0= REMOTE_MAC,
.maclen ="\x10",
};
nrf_config_set(&config);
};
void process(uint8_t * input){
__attribute__ ((aligned (4))) uint8_t buf[32];
puts("process: ");
puts(input);
puts("\r\n");
if(input[0]=='M'){
buf[0]=0x10; // Length: 16 bytes
buf[1]='M'; // Proto
buf[2]=0x01;
buf[3]=0x01; // Unused
uint32touint8p(0,buf+4);
uint32touint8p(0x41424344,buf+8);
buf[12]=0xff; // salt (0xffff always?)
buf[13]=0xff;
nrf_snd_pkt_crc_encr(16,buf,remotekey);
nrf_rcv_pkt_start();
};
};
#define INPUTLEN 99
void r_recv(void){
__attribute__ ((aligned (4))) uint8_t buf[32];
int len;
uint8_t input[INPUTLEN+1];
int inputptr=0;
nrf_rcv_pkt_start();
puts("D start");
getInputWaitRelease();
while(!getInputRaw()){
delayms(100);
// Input
int l=INPUTLEN-inputptr;
CDC_OutBufAvailChar (&l);
if(l>0){
CDC_RdOutBuf (input+inputptr, &l);
input[inputptr+l+1]=0;
for(int i=0;i<l;i++){
if(input[inputptr+i] =='\r'){
input[inputptr+i]=0;
process(input);
if(i<l)
memmove(input,input+inputptr+i+1,l-i);
inputptr=-i-1;
break;
};
};
};
inputptr+=l;
len=nrf_rcv_pkt_poll_dec(sizeof(buf),buf,remotekey);
// Receive
if(len<=0){
delayms(10);
continue;
};
if(buf[1]=='C'){ // Cursor
puts("C ");
puts(IntToStrX( buf[2],2 ));
puts(" ");
puts(IntToStrX( uint8ptouint32(buf+4), 8 ));
puts(" ");
puts(IntToStrX( uint8ptouint32(buf+8), 8 ));
}else{
puts("U ");
// puts("[");puts(IntToStrX(len,2));puts("] ");
puts(IntToStrX( *(int*)(buf+ 0),2 ));
puts(" ");
puts(IntToStrX( *(int*)(buf+ 1),2 ));
puts(" ");
puts(IntToStrX( *(int*)(buf+ 2),2 ));
puts(" ");
puts(IntToStrX( *(int*)(buf+ 3),2 ));
puts(" ");
puts(IntToStrX( uint8ptouint32(buf+4),8 ));
puts(".");
puts(IntToStrX( uint8ptouint32(buf+8),8 ));
puts(" ");
puts(IntToStrX( uint8ptouint32(buf+10),4 ));
};
puts("\r\n");
};
nrf_rcv_pkt_end();
puts("D exit");
}
void r_s1(void){
static int ctr=1;
__attribute__ ((aligned (4))) uint8_t buf[32];
int status;
buf[0]=0x10; // Length: 16 bytes
buf[1]='1'; // Proto
buf[2]=0x00;
buf[3]=0x00; // Unused
uint32touint8p(ctr++,buf+4);
uint32touint8p(0x5ec,buf+8);
buf[12]=0xff; // salt (0xffff always?)
buf[13]=0xff;
status=nrf_snd_pkt_crc_encr(16,buf,remotekey);
lcdClear();
lcdPrint("F-St:"); lcdPrintInt(status);
lcdDisplay();
};
void r_s2(void){
static int ctr=1;
__attribute__ ((aligned (4))) uint8_t buf[32];
int status;
buf[0]=0x10; // Length: 16 bytes
buf[1]='C'; // Proto
buf[2]=0x00;
buf[3]=0x00; // Unused
uint32touint8p(ctr++,buf+4);
uint32touint8p(0x5ec,buf+8);
buf[12]=0xff; // salt (0xffff always?)
buf[13]=0xff;
status=nrf_snd_pkt_crc_encr(16,buf,remotekey);
buf[0]=0x10; // Length: 16 bytes
buf[1]='I'; // Proto
buf[2]=0x00;
buf[3]=0x00; // Unused
uint32touint8p(ctr++,buf+4);
uint32touint8p(0x5ec,buf+8);
buf[12]=0xff; // salt (0xffff always?)
buf[13]=0xff;
status=nrf_snd_pkt_crc_encr(16,buf,remotekey);
lcdClear();
lcdPrint("F-St:"); lcdPrintInt(status);
lcdDisplay();
};
void r_send(void){
int ctr=1;
__attribute__ ((aligned (4))) uint8_t buf[32];
int len;
int status;
while(1){
buf[0]=0x10; // Length: 16 bytes
buf[1]='C'; // Proto
buf[2]=getInputRaw();
buf[3]=0x00; // Unused
ctr++;
*(int*)(buf+4)=ctr;
/*
buf[4]=0x00; // ctr
buf[5]=0x00; // ctr
buf[6]=0x00; // ctr
buf[7]=ctr++; // ctr
*/
buf[8]=0x0; // Object id
buf[9]=0x0;
buf[10]=0x05;
buf[11]=0xec;
buf[12]=0xff; // salt (0xffff always?)
buf[13]=0xff;
lcdClear();
lcdPrint("Key:"); lcdPrintInt(buf[2]); lcdNl();
if(buf[2]==BTN_ENTER)
break;
status=nrf_snd_pkt_crc_encr(16,buf,remotekey);
lcdPrint("F-St:"); lcdPrintInt(status);
lcdDisplay();
len=nrf_rcv_pkt_time_encr(100,sizeof(buf),buf,remotekey);
if(len>0){
lcdPrint("Got!");
lcdDisplay();
break;
};
delayms(10);
};
};

View File

@ -0,0 +1,139 @@
#include <sysinit.h>
#include "basic/basic.h"
#include "lcd/lcd.h"
#include "lcd/print.h"
#include "funk/nrf24l01p.h"
#include "usbcdc/usb.h"
#include "usbcdc/usbcore.h"
#include "usbcdc/usbhw.h"
#include "usbcdc/cdcuser.h"
#include "usbcdc/cdc_buf.h"
#include "usbcdc/util.h"
#include <string.h>
#define BEACON_CHANNEL 81
#define BEACON_MAC "\x1\x2\x3\x2\1"
uint32_t const testkey[4] = {
0xB4595344,0xD3E119B6,0xA814D0EC,0xEFF5A24E
};
#if CFG_USBMSC
#error "MSC is defined"
#endif
#if !CFG_USBCDC
#error "CDC is not defined"
#endif
/**************************************************************************/
void ser_enable(void) {
usbCDCInit();
};
void ser_disable(void) {
usbCDCOff();
};
#define myLEN 10
void ser_read(){
uint8_t buf[myLEN+1];
int l=myLEN;
lcdPrint("Bytes:");
CDC_OutBufAvailChar (&l);
lcdPrintInt(l);
lcdNl();
lcdPrint("read:");
CDC_RdOutBuf (buf, &l);
lcdPrintInt(l);
lcdNl();
buf[l]=0;
lcdPrintln(buf);
};
void ser_say(){
puts("hello world\r\n");
};
void f_init(){
nrf_init();
struct NRF_CFG config = {
.channel= BEACON_CHANNEL,
.txmac= BEACON_MAC,
.nrmacs=1,
.mac0= BEACON_MAC,
.maclen ="\x10",
};
nrf_config_set(&config);
};
void f_beacon(void){
struct NRF_CFG config = {
.channel= BEACON_CHANNEL,
.txmac= BEACON_MAC,
.nrmacs=1,
.mac0= BEACON_MAC,
.maclen ="\x10",
};
nrf_config_set(&config);
};
int enctoggle=0;
void f_enctog(){
enctoggle=1-enctoggle;
lcdClear();
lcdPrint("Encryption:");
if(enctoggle)
lcdPrintln("ON");
else
lcdPrintln("Off");
};
void f_recser(void){
__attribute__ ((aligned (4))) uint8_t buf[32];
int len;
getInputWaitRelease();
do{
len=nrf_rcv_pkt_time_encr(1000,sizeof(buf),buf,enctoggle?testkey:NULL);
if(len==0){
puts("(Timeout)\r\n");
};
puts("pkt: ");
puts("[");puts(IntToStrX(len,2));puts("] ");
puts(IntToStrX( *(int*)(buf+ 0),2 ));
puts(" ");
puts(IntToStrX( *(int*)(buf+ 1),2 ));
puts(" ");
puts(IntToStrX( *(int*)(buf+ 2),2 ));
puts(" ");
puts(IntToStrX( *(int*)(buf+ 3),2 ));
puts(".");
puts(IntToStrX( *(int*)(buf+ 4),8 ));
puts(".");
puts(IntToStrX( *(int*)(buf+ 8),8 ));
puts(".");
puts(IntToStrX( *(int*)(buf+ 12),4 ));
puts(" [");
len=crc16(buf,14);
puts(IntToStrX(len,4)); puts("]\r\n");
delayms(10);
}while ((getInputRaw())==BTN_NONE);
};

View File

@ -0,0 +1,128 @@
#include <sysinit.h>
#include "basic/basic.h"
#include "lcd/lcd.h"
#include "lcd/print.h"
#include "lcd/allfonts.h"
#include "filesystem/ff.h"
#include "filesystem/select.h"
#include "funk/nrf24l01p.h"
#include "usb/usbmsc.h"
#include <string.h>
/**************************************************************************/
void show_ticks(void) {
int dx=0;
int dy=8;
lcdClear();
dx=DoString(0,dy,"Ticks:");
while ((getInputRaw())==BTN_NONE){
DoInt(0,dy+8,_timectr);
lcdDisplay();
};
dy+=16;
dx=DoString(0,dy,"Done.");
};
void chrg_stat(void) {
int stat;
while ((getInputRaw())==BTN_NONE){
lcdClear();
lcdPrintln("Chrg_stat:");
stat=gpioGetValue(RB_PWR_CHRG);
lcdPrint(IntToStr(stat,3,0));
lcdNl();
lcdRefresh();
};
lcdPrintln("Done.");
};
void adc_light(void) {
int dx=0;
int dy=8;
dx=DoString(0,dy,"Light:");
DoString(0,dy+16,"Night:");
while ((getInputRaw())==BTN_NONE){
DoInt(dx,dy,GetLight());
DoInt(dx,dy+16,isNight());
DoInt(dx,dy+8,GLOBAL(daytrig));
lcdDisplay();
};
dy+=8;
dx=DoString(0,dy,"Done.");
};
void uptime(void) {
int t;
int h;
char flag;
while ((getInputRaw())==BTN_NONE){
lcdClear();
lcdPrintln("Uptime:");
t=getTimer()/(1000/SYSTICKSPEED);
h=t/60/60;
flag=F_ZEROS;
if(h>0){
lcdPrint(IntToStr(h,2,flag));
lcdPrint("h");
flag|=F_LONG;
};
h=t/60%60;
if(h>0){
lcdPrint(IntToStr(h,2,flag));
lcdPrint("m");
flag|=F_LONG;
};
h=t%60;
if(h>0){
lcdPrint(IntToStr(h,2,flag));
lcdPrint("s");
};
lcdNl();
lcdRefresh();
delayms_queue(200);
};
lcdPrintln("done.");
};
void gotoISP(void) {
DoString(0,0,"Enter ISP!");
lcdDisplay();
ISPandReset();
}
void lcd_mirror(void) {
lcdToggleFlag(LCD_MIRRORX);
};
void lcd_invert(void) {
lcdToggleFlag(LCD_INVERTED);
};
void adc_check(void) {
int dx=0;
int dy=8;
// Print Voltage
dx=DoString(0,dy,"Voltage:");
while ((getInputRaw())==BTN_NONE){
DoInt(dx,dy,GetVoltage());
lcdDisplay();
};
dy+=8;
dx=DoString(0,dy,"Done.");
};
void msc_menu(void){
DoString(0,8,"MSC Enabled.");
lcdDisplay();
usbMSCInit();
getInputWaitRelease();
getInputWait();
DoString(0,16,"MSC Disabled.");
usbMSCOff();
};

View File

@ -0,0 +1,26 @@
#include <sysinit.h>
#include "basic/basic.h"
#include "lcd/lcd.h"
#include "lcd/print.h"
#include "funk/nrf24l01p.h"
#include <string.h>
#include "funk/rftransfer.h"
#include "funk/openbeacon.h"
#include "core/iap/iap.h"
/**************************************************************************/
void f_uuid(void) {
IAP_return_t iap_return;
iap_return = iapReadSerialNumber();
lcdPrintIntHex(iap_return.Result[0]); lcdNl();
lcdPrintIntHex(iap_return.Result[1]); lcdNl();
lcdPrintIntHex(iap_return.Result[2]); lcdNl();
lcdPrintIntHex(iap_return.Result[3]); lcdNl();
}

View File

@ -6,52 +6,201 @@
#include "basic/basic.h"
#include "lcd/render.h"
#include "lcd/allfonts.h"
#include "basic/config.h"
#include "basic/byteorder.h"
#include "lcd/lcd.h"
#include "lcd/print.h"
#include "funk/nrf24l01p.h"
#include "usbcdc/usb.h"
#include "usbcdc/usbcore.h"
#include "usbcdc/usbhw.h"
#include "usbcdc/cdcuser.h"
#include "usbcdc/cdc_buf.h"
#include "usbcdc/util.h"
#include "core/ssp/ssp.h"
#include "ecc.c"
void backlightInit(void);
#if CFG_USBMSC
#error "MSC is defined"
#endif
/**************************************************************************/
#if !CFG_USBCDC
#error "CDC is not defined"
#endif
void main_schneider(void) {
//int yctr=8;
int dx=0;
char key;
int ctr = 1;
backlightInit();
font_direction = FONT_DIR_LTR; // LeftToRight is the default
//yctr=18;
bitstr_parse(poly, "800000000000000000000000000000000000000c9");
bitstr_parse(coeff_b, "20a601907b8c953ca1481eb10512f78744a3205fd");
bitstr_parse(base_x, "3f0eba16286a2d57ea0991168d4994637e8343e36");
bitstr_parse(base_y, "0d51fbc6c71a0094fa2cdd545b11c5c0c797324f1");
bitstr_parse(base_order, "40000000000000000000292fe77e70c12a4234c33");
#define CHANNEL 81
#define MAC "\x1\x2\x3\x2\x1"
ECIES_generate_key_pair(); // generate a public/private key pair
while (1) {
key= getInput();
font=&Font_7x8;
#define SERIAL_NONE 0
#define SERIAL_ESCAPE '\\'
#define SERIAL_STOP '0'
#define SERIAL_PACKETLEN 128
// Easy flashing
if(key==BTN_LEFT){
DoString(0,8,"Enter ISP!");
lcdDisplay();
ISPandReset();
struct NRF_CFG config = {
.channel= CHANNEL,
.txmac= MAC,
.nrmacs=1,
.mac0= MAC,
.maclen ="\x20",
};
// Display nickname
//font = &Font_Ubuntu36pt;
dx=DoString(0,0,"Test");
dx=DoInt(dx,0,ctr++);
lcdDisplay();
encryption_decryption_demo("This is encrypted",
"1c56d302cf642a8e1ba4b48cc4fbe2845ee32dce7",
"45f46eb303edf2e62f74bd68368d979e265ee3c03",
"0e10e787036941e6c78daf8a0e8e1dbfac68e26d2");
uint8_t serialmsg_message[SERIAL_PACKETLEN];
uint8_t serialmsg_len = 0;
void serialmsg_init(void);
uint8_t serialmsg_put(uint8_t data);
char snd_pkt_no_crc(int size, uint8_t * pkt);
void dump_encoded(int len, uint8_t *data);
#define INPUTLEN 99
/**************************************************************************/
void main_schneider(void)
{
GLOBAL(daytrig)=10;
GLOBAL(lcdbacklight)=10;
char input[64];
usbCDCInit();
delayms(500);
nrf_init();
nrf_config_set(&config);
nrf_rcv_pkt_start();
while(1){
int l, i, status;
CDC_OutBufAvailChar (&l);
if(l>0){
CDC_RdOutBuf (input, &l);
for(i=0; i<l; i++){
uint8_t cmd = serialmsg_put(input[i]);
if( cmd != SERIAL_NONE ){
switch( cmd ){
case '1':
// can we loose packets here?
nrf_rcv_pkt_end();
status=snd_pkt_no_crc(serialmsg_len, serialmsg_message);
//status=nrf_snd_pkt_crc(serialmsg_len, serialmsg_message);
nrf_rcv_pkt_start();
break;
case '3':
memcpy(config.txmac, serialmsg_message, 5);
nrf_config_set(&config);
break;
case '4':
memcpy(config.mac0, serialmsg_message, 5);
nrf_config_set(&config);
break;
case '5':
config.channel=serialmsg_message[0];
nrf_config_set(&config);
break;
case '6':
config.maclen[0]=serialmsg_message[0];
nrf_config_set(&config);
break;
};
puts("\\2\\0");
}
return;
}
}
int len;
uint8_t buf[32];
len=nrf_rcv_pkt_poll(sizeof(buf),buf);
if( len > 0 ){
puts("\\1");
dump_encoded(len, buf);
puts("\\0");
}
}
}
void dump_encoded(int len, uint8_t *data)
{
int i=0,j=0;
uint8_t buf[SERIAL_PACKETLEN*2];
for(i=0; i<len; i++){
if( data[i] == SERIAL_ESCAPE ){
buf[j++] = SERIAL_ESCAPE;
}
buf[j++] = data[i];
}
CDC_WrInBuf((char*)buf, &j);
}
void tick_schneider(void){
return;
};
inline void xmit_spi(uint8_t dat) {
sspSend(0, (uint8_t*) &dat, 1);
}
inline void rcv_spi(uint8_t *dat) {
sspReceive(0, dat, 1);
}
#define CS_LOW() gpioSetValue(RB_SPI_NRF_CS, 0)
#define CS_HIGH() gpioSetValue(RB_SPI_NRF_CS, 1)
#define CE_LOW() gpioSetValue(RB_NRF_CE, 0)
#define CE_HIGH() gpioSetValue(RB_NRF_CE, 1)
char snd_pkt_no_crc(int size, uint8_t * pkt)
{
if(size > MAX_PKT)
size=MAX_PKT;
nrf_write_reg(R_CONFIG,
R_CONFIG_PWR_UP| // Power on
R_CONFIG_EN_CRC // CRC on, single byte
);
CS_LOW();
xmit_spi(C_W_TX_PAYLOAD);
sspSend(0,pkt,size);
CS_HIGH();
CE_HIGH();
delayms(1); // Send it. (only needs >10ys, i think)
CE_LOW();
return nrf_cmd_status(C_NOP);
};
void serialmsg_init(void)
{
serialmsg_len = 0;
}
//returns the message type or SERIAL_NONE
uint8_t serialmsg_put(uint8_t data)
{
static uint8_t escaped = 0;
static uint8_t msgtype = SERIAL_NONE;
if( data == SERIAL_ESCAPE && escaped == 0 ){
//a control code will follow
escaped = 1;
return SERIAL_NONE;
}else if( escaped ){
escaped = 0;
if( data != SERIAL_ESCAPE ){
if( data == SERIAL_STOP ){
uint8_t tmp = msgtype;
msgtype = SERIAL_NONE;
return tmp;
}
msgtype = data;
serialmsg_len=0;
return SERIAL_NONE;
}
}
serialmsg_message[serialmsg_len++] = data;
//prevent a buffer overflow
if( serialmsg_len == SERIAL_PACKETLEN )
serialmsg_len--;
return SERIAL_NONE;
}

312
firmware/l0dable/r_player.c Normal file
View File

@ -0,0 +1,312 @@
#include <sysinit.h>
#include "basic/basic.h"
#include "basic/byteorder.h"
#include "lcd/lcd.h"
#include "lcd/print.h"
#include "funk/nrf24l01p.h"
#include <string.h>
#include "basic/random.h"
#include "basic/config.h"
#include "usetable.h"
//channel and mac used to transmit game announcements
#define ANNOUNCE_CHANNEL 81
#define ANNOUNCE_MAC "REM0T"
struct NRF_CFG config;
struct packet{
uint8_t len;
uint8_t protocol;
uint8_t command;
uint32_t id;
uint32_t ctr;
//union with 19 bytes data
union content{
struct button{
uint8_t button;
uint8_t reserved[18];
}__attribute__((packed)) button;
struct text{
uint8_t x;
uint8_t y;
uint8_t flags;
uint8_t text[16];
}__attribute__((packed)) text;
struct nick{
uint8_t flags;
uint8_t nick[18];
}__attribute__((packed)) nick;
struct nickrequest{
uint8_t reserved[19];
}__attribute__((packed)) nickrequest;
struct ack{
uint8_t flags;
uint8_t reserved[18];
}__attribute__((packed)) ack;
struct announce{
uint8_t gameMac[5];
uint8_t gameChannel;
//uint8_t playerMac[5]; playerMac = gameMac+1;
uint32_t gameId;
uint8_t gameFlags;
uint8_t gameTitle[8];
}__attribute__((packed)) announce;
struct join{
uint32_t gameId;
uint8_t reserved[15];
}__attribute__((packed)) join;
}c;
uint16_t crc;
}__attribute__((packed));
#define FLAGS_MASS_GAME 1
#define FLAGS_ACK_JOINOK 1
#define MASS_ID 1
/**************************************************************************/
/* l0dable for playing games which are announced by other r0kets with the l0dabel r_game */
/* Values of buf[3]:
* B: packet sent by player, contain information which button is pressed
* T: packet sent by game, contain text for display
* N: packet sent by game, requesting nick
* n: packet sent player, containing nick
* A: packet sent by game, announcing game
* J: packet sent by player, requesting to join game
* a: ack, packet with $ctr was received
*/
uint32_t ctr;
uint32_t id;
uint32_t gameId;
void sendButton(uint8_t button);
void sendJoin(uint32_t game);
void processPacket(struct packet *p);
void processAnnounce(struct announce *a);
uint8_t selectGame();
void playGame();
struct announce games[7];
uint8_t gamecount;
void ram(void)
{
int priv = GLOBAL(privacy);
GLOBAL(privacy) = 3;
config.nrmacs=1;
config.maclen[0] = 32;
config.channel = ANNOUNCE_CHANNEL;
memcpy(config.mac0, ANNOUNCE_MAC, 5);
nrf_config_set(&config);
id = getRandom();
ctr = 1;
while( selectGame() ){
playGame();
}
GLOBAL(privacy) = priv;
};
void playGame(void)
{
int len;
struct packet p;
while(1){
uint8_t button = getInputRaw();
sendButton(button);
while(1){
len = nrf_rcv_pkt_time(32,sizeof(p),(uint8_t*)&p);
if(len==sizeof(p)){
processPacket(&p);
}else{
break;
}
}
delayms(20);
};
}
void showGames(uint8_t selected)
{
int i;
lcdClear();
lcdPrintln("Games:");
if( gamecount ){
for(i=0;i<gamecount;i++){
if( i==selected )
lcdPrint("*");
else
lcdPrint(" ");
char buf[9];
memcpy(buf, games[i].gameTitle, 8);
buf[8] = 0;
lcdPrintln(buf);
}
}else{
lcdPrint("*No Games");
}
lcdRefresh();
}
uint8_t joinGame()
{
int i;
struct packet p;
p.len=sizeof(p);
p.protocol='G';
p.command='J';
p.id= id;
p.ctr= ++ctr;
p.c.join.gameId=gameId;
lcdClear();
lcdPrintln("Joining game");
lcdRefresh();
for(i=0; i<10; i++){
nrf_snd_pkt_crc(sizeof(p),(uint8_t*)&p);
int len = nrf_rcv_pkt_time(30,sizeof(p),(uint8_t*)&p);
if( len==sizeof(p) ){
if( (p.len==32) && (p.protocol=='G') && p.command=='a' ){ //check sanity, protocol
if( p.id == id && p.ctr == ctr ){
if( p.c.ack.flags & FLAGS_ACK_JOINOK ){
lcdPrintln("Join OK");
lcdRefresh();
return 1;
}else{
lcdPrintln("Join rejected");
lcdRefresh();
getInputWait();
getInputWaitRelease();
return 0;
}
}
}
}
delayms(70);
}
lcdPrintln("timeout :(");
lcdRefresh();
getInputWait();
getInputWaitRelease();
return 0;
}
uint8_t selectGame()
{
int len, i, selected;
struct packet p;
int a = 0;
config.channel = ANNOUNCE_CHANNEL;
memcpy(config.mac0, ANNOUNCE_MAC, 5);
nrf_config_set(&config);
gamecount = 0;
for(i=0;i<60;i++){
len= nrf_rcv_pkt_time(30, sizeof(p), (uint8_t*)&p);
if (len==sizeof(p)){
if( a ) a = 0; else a = 1;
gpioSetValue (RB_LED2, a);
processPacket(&p);
}
}
selected = 0;
while(1){
showGames(selected);
int key=getInputWait();
getInputWaitRelease();
switch(key){
case BTN_DOWN:
if( selected < gamecount-1 ){
selected++;
}
break;
case BTN_UP:
if( selected > 0 ){
selected--;
}
break;
case BTN_LEFT:
return 0;
case BTN_ENTER:
case BTN_RIGHT:
if( gamecount == 0 )
return 0;
gameId = games[selected].gameId;
memcpy(config.txmac, games[selected].gameMac, 5);
memcpy(config.mac0, games[selected].gameMac, 5);
config.mac0[4]++;
config.channel = games[selected].gameChannel;
nrf_config_set(&config);
if( games[selected].gameFlags & FLAGS_MASS_GAME )
return 1;
else
return joinGame();
}
}
}
void processNickRequest( struct nickrequest *nq)
{
struct packet p;
p.len=sizeof(p);
p.protocol='G'; // Proto
p.command='n';
p.id= id;
p.ctr= ++ctr;
p.c.nick.flags = 0;
uint8_t *nick = GLOBAL(nickname);
strcpy(p.c.nick.nick, nick);
nrf_snd_pkt_crc(sizeof(p),(uint8_t*)&p);
}
void processPacket(struct packet *p)
{
if ((p->len==32) && (p->protocol=='G') && (p->id == id || p->id == 0) ){ //check sanity, protocol, id
if (p->command=='T'){
//processText(&(p->c.text));
}
else if (p->command=='N'){
processNickRequest(&(p->c.nickrequest));
}
else if (p->command=='A'){
processAnnounce(&(p->c.announce));
}
}
}
void processAnnounce(struct announce *a)
{
if( gamecount < sizeof(games)/sizeof(games[0]) ){
games[gamecount] = *a;
gamecount++;
}
}
//increment ctr and send button state, id and ctr
void sendButton(uint8_t button)
{
struct packet p;
p.len=sizeof(p);
p.protocol='G'; // Proto
p.command='B';
p.id= id;
p.ctr= ++ctr;
p.c.button.button=button;
//lcdClear();
//lcdPrint("Key:"); lcdPrintInt(buf[2]); lcdNl();
nrf_snd_pkt_crc(sizeof(p),(uint8_t*)&p);
}

View File

@ -1,4 +0,0 @@
*.elf
*.bin
*.h
loadable.ld

View File

@ -1,12 +0,0 @@
# Make doesn't allow dependencies on parent directory, so we need to
# run make from one level up:
MAKEFILE=loadable/Makefile.sub
MAKE+=--no-print-directory
all:
@cd .. && $(MAKE) -f $(MAKEFILE)
clean:
@cd .. && $(MAKE) -f $(MAKEFILE) clean

View File

@ -1,57 +0,0 @@
DIR?= loadable
##########################################################################
# User configuration and firmware specific object files
##########################################################################
SRCS = $(wildcard $(DIR)/*.c)
OBJS = $(foreach mod,$(SRCS),$(subst .c,.o,$(mod)))
ELFS = $(foreach mod,$(SRCS),$(subst .c,.elf,$(mod)))
BINS = $(foreach mod,$(SRCS),$(subst .c,.bin,$(mod)))
HDRS = $(foreach mod,$(SRCS),$(subst .c,.h,$(mod)))
##########################################################################
# GNU GCC compiler flags
##########################################################################
ROOT_PATH?= .
INCLUDE_PATHS = -I$(ROOT_PATH) -I$(ROOT_PATH)/core
include $(ROOT_PATH)/Makefile.inc
##########################################################################
# Compiler settings, parameters and flags
##########################################################################
FIRMWARE=$(ROOT_PATH)/$(OUTFILE).elf
LDSRCFILE=$(DIR)/ram.ld
LDFILE=$(DIR)/loadable.ld
CFLAGS+=-mlong-calls -fno-toplevel-reorder
LDFLAGS+= -R $(FIRMWARE)
all: $(OBJS) $(ELFS) $(BINS) $(HDRS)
$(LDFILE):
-@echo "MEMORY" > $(LDFILE)
-@echo "{" >> $(LDFILE)
-@echo " sram(rwx): ORIGIN = 0x10002000 - $(RAMCODE), LENGTH = $(RAMCODE)" >> $(LDFILE)
-@echo "}" >> $(LDFILE)
-@echo "INCLUDE $(LDSRCFILE)" >> $(LDFILE)
%.o : %.c
$(CC) $(CFLAGS) -o $@ $<
%.elf: %.o $(FIRMWARE) $(LDFILE)
$(LD) $(LDFLAGS) -T $(LDFILE) -o $@ $<
$(SIZE) $@
%.bin: %.elf
$(OBJCOPY) $(OCFLAGS) -O binary $< $@
%.h: %.bin $(DIR)/bin2h.pl
$(DIR)/bin2h.pl $<
clean:
cd $(DIR) && rm -f *.o *.elf *.bin
.SUFFIXES:
.PHONY: $(LDFILE)

View File

@ -1,41 +0,0 @@
#!/usr/bin/perl
#
# vim:set ts=4 sw=4:
use strict;
sub dwim{
local $/=undef;
my $file=shift;
open(IN,"<:bytes",$file) || die "Can't open $file: $!";
my @bytes=unpack("C*",<IN>);
close(IN);
$file=~s/\.[^.]+$//;
open(OUT,">","${file}.h") || die "Can't write ${file}.h: $!";
$file=~s!.*/!!;
print OUT "const uint16_t loadable_${file}_size = ", scalar @bytes, ";\n";
print OUT "const uint8_t loadable_${file}[] = {\n";
my $ctr=0;
for(@bytes){
print OUT "\t" if($ctr==0);
printf OUT "0x%02x, ",$_;
if(++$ctr==8){
print OUT "\n";
$ctr=0;
};
};
print OUT "\n" if($ctr!=0);
print OUT "};\n";
close(OUT);
};
for(@ARGV){
dwim($_);
};

View File

@ -1,10 +0,0 @@
#include <sysinit.h>
#include "basic/basic.h"
void ram(void){
for (int x=0;x<20;x++){
gpioSetValue (RB_LED1, x%2);
delayms(50);
};
};

View File

@ -1,190 +0,0 @@
#include <sysinit.h>
#include "basic/basic.h"
#include "lcd/render.h"
#include "lcd/display.h"
#include "lcd/allfonts.h"
#define FIXSIZE 25
#define mul(a,b) ((((long long)a)*(b))>>FIXSIZE)
#define fixpt(a) ((long)(((a)*(1<<FIXSIZE))))
#define integer(a) (((a)+(1<<(FIXSIZE-1)))>>FIXSIZE)
#define ZOOM_RATIO 0.90
#define ITERATION_MAX 150
void mandelInit();
void mandelMove();
void mandelUpdate();
void ram(void) {
int key;
mandelInit();
while (1) {
lcdDisplay();
mandelMove();
mandelUpdate();
// Exit on enter+direction
key=getInputRaw();
if(key&BTN_ENTER && key>BTN_ENTER)
return;
}
return;
}
struct mb {
long rmin, rmax, imin, imax;
bool dirty, dup, ddown, dleft, dright, clickmark;
int count, limitZIn, limitZOut;
} mandel;
void mandelInit() {
//mandel.rmin = -2.2*0.9;
//mandel.rmax = 1.0*0.9;
//mandel.imin = -2.0*0.9;
//mandel.imax = 2.0*0.9;
mandel.rmin = fixpt(-2);
mandel.rmax = fixpt(1);
mandel.imin = fixpt(-2);
mandel.imax = fixpt(2);
mandel.count = 0;
mandel.limitZIn = 40;
mandel.limitZOut = 30;
mandel.dirty = true;
mandel.dup = false;
mandel.ddown = false;
mandel.dleft = false;
mandel.dright = false;
mandel.clickmark = false;
}
void mandelMove() {
//long delta_r = (mandel.rmax - mandel.rmin)/10;
//long delta_i = (mandel.imax - mandel.imin)/10;
long rs =(mandel.rmax-mandel.rmin)/RESY;
long is =(mandel.imax-mandel.imin)/RESX;
char key = getInputRaw();
if (key == BTN_LEFT) {
mandel.imax -=is;
mandel.imin -=is;
mandel.dleft = true;
} else if (key == BTN_RIGHT) {
mandel.imax += is;
mandel.imin += is;
mandel.dright = true;
} else if (key == BTN_DOWN) {
mandel.rmax += rs;
mandel.rmin += rs;
mandel.ddown = true;
} else if (key == BTN_UP) {
mandel.rmax -= rs;
mandel.rmin -= rs;
mandel.dup = true;
} else if (key == BTN_ENTER) {
if (mandel.count < mandel.limitZIn) {
mandel.count = mandel.count + 1;
}
} else if (key == BTN_NONE) {
if(mandel.count > 0 ) {
mandel.count = mandel.count - 1;
mandel.clickmark = true;
}
if (mandel.count == 0 ) {
mandel.clickmark = false;
}
}
if (mandel.count > mandel.limitZOut && mandel.clickmark && key == BTN_ENTER) {
mandel.imin = mandel.imin - (mandel.imax-mandel.imin)/10;
mandel.imax = mandel.imax + (mandel.imax-mandel.imin)/10;
mandel.rmin = mandel.rmin -(mandel.rmax-mandel.rmin)/10;
mandel.rmax = mandel.rmax +(mandel.rmax-mandel.rmin)/10;
mandel.dirty = true;
}
if (mandel.count == mandel.limitZIn && key == BTN_ENTER) {
mandel.imin = mandel.imin + (mandel.imax-mandel.imin)/10;
mandel.imax = mandel.imax - (mandel.imax-mandel.imin)/10;
mandel.rmin = mandel.rmin +(mandel.rmax-mandel.rmin)/10;
mandel.rmax = mandel.rmax -(mandel.rmax-mandel.rmin)/10;
mandel.dirty = true;
}
}
void mandelPixel(int x, int y) {
long r0,i0,rn, p,q;
long rs,is;
int iteration;
rs=(mandel.rmax-mandel.rmin)/RESY;
is=(mandel.imax-mandel.imin)/RESX;
//p=fixpt(mandel.rmin+y*rs);
//q=fixpt(mandel.imin+x*is);
p=mandel.rmin+y*rs;
q=mandel.imin+x*is;
rn=0;
r0=0;
i0=0;
iteration=0;
while ((mul(rn,rn)+mul(i0,i0))<fixpt(4) && ++iteration<ITERATION_MAX) {
rn=mul((r0+i0),(r0-i0)) +p;
i0=mul(fixpt(2),mul(r0,i0)) +q;
r0=rn;
}
if (iteration==ITERATION_MAX) iteration=1;
bool pixel = ( iteration>1);
lcdSetPixel(x, y, pixel);
}
void mandelUpdate() {
int xmin,xmax,ymin,ymax;
if (mandel.dirty) {
xmin = 0;
xmax = RESX;
ymin = 0;
ymax = RESY;
mandel.dirty = false;
} else if (mandel.dleft) {
lcdShift(1,0,false);
xmin = 0;
xmax = 1;
ymin = 0;
ymax = RESY;
mandel.dleft = false;
} else if (mandel.dright) {
lcdShift(-1,0,false);
xmin = RESX-1;
xmax = RESX;
ymin = 0;
ymax = RESY;
mandel.dright = false;
} else if (mandel.dup) {
lcdShift(0,-1,true);
xmin=0;
xmax=RESX;
ymin=0;
ymax=1;
mandel.dup = false;
} else if (mandel.ddown) {
lcdShift(0,1,true);
xmin=0;
xmax=RESX;
ymin=RESY-1;
ymax=RESY;
mandel.ddown = false;
} else {
return;
}
for (int x = xmin; x<xmax; x++) {
for (int y = ymin; y<ymax; y++) {
mandelPixel(x,y);
}
}
}

View File

@ -1,47 +0,0 @@
sram_top = ORIGIN(sram) + LENGTH(sram);
ENTRY(boot_entry)
SECTIONS
{
.text :
{
*(.text*)
*(.rodata*)
} > sram
/*
* More information about Special Section Indexes is available in the
* free "ELF for the ARM Architecture" document from ARM Limited
* http://infocenter.arm.com/help/topic/com.arm.doc.ihi0044d/IHI0044D_aaelf.pdf
*
*/
.ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } > sram
__exidx_start = .;
.ARM.exidx : { *(.ARM.exidx* .gnu.linkonce.armexidx.*) } > sram
__exidx_end = .;
_etext = .;
.data : AT (__exidx_end)
{
_data = .;
*(vtable)
*(.data*)
_edata = .;
} > sram
/* zero initialized data */
.bss :
{
_bss = .;
*(.bss*)
*(COMMON)
_ebss = .;
} > sram
end = .;
/* For GDB compatibility we decrease the top with 16 bytes */
stack_entry = sram_top - 16;
}

View File

@ -1,338 +0,0 @@
#include <sysinit.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdint.h>
#include "basic/basic.h"
#include "lcd/render.h"
#include "lcd/allfonts.h"
#include "basic/ecc.h"
#include "funk/nrf24l01p.h"
#include "filesystem/ff.h"
#include "filesystem/diskio.h"
#include "funk/filetransfer.h"
#include "lcd/print.h"
uint8_t mac[5] = {1,2,3,2,1};
void ram(void)
{
if( sendKeys() )
return;
char priv[42];
UINT readbytes;
FIL file;
if( f_open(&file, "priv.key", FA_OPEN_EXISTING|FA_READ) ){
return;
}
if( f_read(&file, priv, 41, &readbytes) || readbytes != 41 ){
return;
}
f_close(&file);
priv[41] = 0;
uint8_t done = 0;
uint8_t key;
uint8_t k1[16], k2[16], rx[4*NUMWORDS], ry[4*NUMWORDS];
while( !done ){
lcdClear();
lcdPrintln("Receiving file");
lcdPrintln("Down=Abort");
lcdRefresh();
key = getInput();
delayms(20);
if( key == BTN_DOWN ){
return -1;
}
if( receiveR(rx,ry) )
continue;
lcdPrintln("Creating key");
lcdRefresh();
ECIES_decryptkeygen(rx, ry, k1, k2, priv);
if( filetransfer_receive(mac,(uint32_t*)k1) < 0 )
continue;
lcdPrintln("Right=OK");
lcdPrintln("Left=Retry");
lcdPrintln("Down=Abort");
lcdRefresh();
while(1){
key = getInput();
delayms(20);
if( key == BTN_LEFT ){
break;
}else if( key == BTN_RIGHT ){
done = 1;
break;
}else if( key == BTN_DOWN ){
return -1;
}
}
}
}
void sendPublicKey(void)
{
uint8_t exp[2 + 4*NUMWORDS + 2];
char buf[42];
UINT readbytes;
FIL file;
if( f_open(&file, "pubx.key", FA_OPEN_EXISTING|FA_READ) ){
return;
}
if( f_read(&file, buf, 41, &readbytes) || readbytes != 41 ){
return;
}
f_close(&file);
buf[41] = 0;
exp[0] = 'P';
bitstr_parse_export((char*)exp+2, buf);
exp[1] = 'X';
nrf_snd_pkt_crc(32, exp);
delayms(10);
if( f_open(&file, "puby.key", FA_OPEN_EXISTING|FA_READ) ){
return;
}
if( f_read(&file, buf, 41, &readbytes) || readbytes != 41 ){
return;
}
f_close(&file);
buf[41] = 0;
exp[1] = 'Y';
bitstr_parse_export((char*)exp+2, buf);
nrf_snd_pkt_crc(32, exp);
delayms(10);
}
int receiveKey(uint8_t type, uint8_t *x, uint8_t *y)
{
uint8_t buf[32];
uint8_t n;
n = nrf_rcv_pkt_time(1000, 32, buf);
if( n == 32 && buf[0] == type && buf[1] == 'X' ){
for(int i=0; i<NUMWORDS*4; i++)
x[i] = buf[i+2];
n = nrf_rcv_pkt_time(100, 32, buf);
if( n == 32 && buf[0] ==type && buf[1] == 'Y' ){
for(int i=0; i<NUMWORDS*4; i++)
y[i] = buf[i+2];
return 0;
}
}
return -1;
}
int receiveR(uint8_t *rx, uint8_t *ry)
{
return receiveKey('R',rx,ry);
}
void sendMac(void)
{
uint8_t buf[32];
buf[0] = 'M';
buf[1] = 'C';
buf[2] = mac[0];
buf[3] = mac[1];
buf[4] = mac[2];
buf[5] = mac[3];
buf[6] = mac[4];
nrf_snd_pkt_crc(32, buf);
delayms(10);
}
int sendKeys(void)
{
uint8_t done = 0;
char key;
while( !done ){
lcdClear();
lcdPrintln("Sending PUBKEY");lcdRefresh();
sendPublicKey();
sendMac();
lcdPrintln("Done");
lcdPrintln("Right=OK");
lcdPrintln("Left=Retry");
lcdPrintln("Down=Abort");
lcdRefresh();
while(1){
key = getInput();
delayms(20);
if( key == BTN_LEFT ){
break;
}else if( key == BTN_RIGHT ){
done = 1;
break;
}else if( key == BTN_DOWN ){
return -1;
}
}
}
return 0;
}
#include <string.h>
#include "funk/nrf24l01p.h"
#include "funk/filetransfer.h"
#include "funk/rftransfer.h"
#include "basic/basic.h"
#include "basic/xxtea.h"
#include "filesystem/ff.h"
#include "lcd/print.h"
int filetransfer_receive(uint8_t *mac, uint32_t const k[4])
{
uint8_t buf[MAXSIZE+1];
uint16_t size;
uint8_t n;
UINT written = 0;
FIL file;
FRESULT res;
//uint8_t macbuf[5];
//nrf_get_rx_max(0,5,macbuf);
uint8_t metadata[32];
//nrf_set_rx_mac(0, 32, 5, mac);
n = nrf_rcv_pkt_time_encr(3000, 32, metadata, k);
if( n != 32 )
return 1; //timeout
//nrf_set_rx_mac(0, 32, 5, macbuf);
//lcdPrintln("got meta"); lcdRefresh();
metadata[19] = 0; //enforce termination
size = (metadata[20] << 8) | metadata[21];
if( size > MAXSIZE ) {lcdPrintln("too big"); lcdRefresh(); while(1);}
if( size > MAXSIZE ) return 1; //file to big
//if(fileexists(metadata)) return 1; //file already exists
//lcdPrint("open"); lcdPrintln((const char*)metadata); lcdRefresh();
res = f_open(&file, (const char*)metadata, FA_OPEN_ALWAYS|FA_WRITE);
//lcdPrintln("file opened"); lcdRefresh();
if( res ) {lcdPrintln("res"); lcdPrint(f_get_rc_string(res)); lcdRefresh(); while(1);}
if( res )
return res;
uint16_t wordcount = (size+3)/4;
//nrf_set_rx_mac(0, 32, 5, mac);
//lcdPrintln("get file"); lcdRefresh();
int fres = rftransfer_receive(buf, wordcount*4, 1000);
if( fres == -1 ){
lcdPrintln("checksum wrong");
}else if( fres == -2 ){
lcdPrintln("timeout");
}else{
//lcdPrintln("got file");
}
lcdRefresh();
if( fres < 0 )
return 1;
//nrf_set_rx_mac(0, 32, 5, macbuf);
xxtea_decode_words((uint32_t *)buf, wordcount, k);
res = f_write(&file, buf, size, &written);
f_close(&file);
if( res )
return res;
if( written != size )
return 1; //error while writing
lcdClear();
lcdPrintln("Received"); lcdPrintln((const char*)metadata); lcdRefresh();
return 0;
}
#define MAXPACKET 32
int16_t rftransfer_receive(uint8_t *buffer, uint16_t maxlen, uint16_t timeout)
{
uint8_t buf[MAXPACKET];
uint8_t state = 0;
uint16_t pos = 0, seq = 0, size = 0, rand = 0, crc = 0;
int n,i;
unsigned int currentTick = systickGetTicks();
unsigned int startTick = currentTick;
while(systickGetTicks() < (startTick+timeout) ){//this fails if either overflows
n = nrf_rcv_pkt_time(1000, MAXPACKET, buf);
switch(state){
case 0:
if( n == 32 && buf[0] == 'L' ){
size = (buf[1] << 8) | buf[2];
rand = (buf[3] << 8) | buf[4];
seq = 0;
pos = 0;
if( size <= maxlen ){
//lcdClear();
//lcdPrint("got l="); lcdPrintInt(size);
//lcdPrintln(""); lcdRefresh();
state = 1;
}
}
break;
case 1:
if( n == 32 && buf[0] == 'D' && ((buf[3]<<8)|buf[4])==rand ){
//lcdPrint("got d"); lcdRefresh();
if( seq == ((buf[1]<<8)|buf[2]) ){
//lcdPrintln(" in seq"); lcdRefresh();
for(i=5; i<n-2 && pos<size; i++,pos++){
buffer[pos] = buf[i];
}
seq++;
}
}
if( pos == size ){
//lcdPrintln("got all"); lcdRefresh();
crc = crc16(buffer, size);
state = 2;
}
break;
case 2:
if( n == 32 && buf[0] == 'C' && ((buf[3]<<8)|buf[4])==rand){
//lcdPrint("got crc"); lcdRefresh();
if( crc == ((buf[1]<<8)|buf[2]) ){
//lcdPrintln(" ok"); lcdRefresh();
return size;
}else{
//lcdPrintln(" nok"); lcdRefresh();
return -1;
}
}
break;
};
}
//lcdPrintln("Timeout"); lcdRefresh();
return -2;
}
int ECIES_decryptkeygen(uint8_t *rx, uint8_t *ry,
uint8_t k1[16], uint8_t k2[16], const char *privkey)
{
elem_t Rx, Ry, Zx, Zy;
exp_t d;
bitstr_import(Rx, (char*)rx);
bitstr_import(Ry, (char*)ry);
if (ECIES_embedded_public_key_validation(Rx, Ry) < 0)
return -1;
bitstr_parse(d, privkey);
point_copy(Zx, Zy, Rx, Ry);
point_mult(Zx, Zy, d);
point_double(Zx, Zy); /* cofactor h = 2 on B163 */
if (point_is_zero(Zx, Zy))
return -1;
ECIES_kdf((char*)k1,(char*) k2, Zx, Rx, Ry);
return 0;
}

View File

@ -1,285 +0,0 @@
#include <sysinit.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdint.h>
#include "basic/basic.h"
#include "lcd/render.h"
#include "lcd/allfonts.h"
#include "basic/ecc.h"
#include "funk/nrf24l01p.h"
#include "filesystem/ff.h"
#include "filesystem/diskio.h"
#include "funk/filetransfer.h"
#include "lcd/print.h"
uint8_t mac[5] = {1,2,3,2,1};
void ram(void)
{
char file[13];
selectFile(file,"TXT");
sendFile(file);
}
void sendR(uint8_t *rx, uint8_t *ry)
{
uint8_t exp[2 + 4*NUMWORDS + 2];
exp[0] = 'R';
for(int i=0; i<4*NUMWORDS; i++)
exp[2+i] = rx[i];
exp[1] = 'X';
nrf_snd_pkt_crc(32, exp);
delayms(10);
exp[1] = 'Y';
for(int i=0; i<4*NUMWORDS; i++)
exp[2+i] = ry[i];
nrf_snd_pkt_crc(32, exp);
delayms(10);
}
int receiveKey(uint8_t type, uint8_t *x, uint8_t *y)
{
uint8_t buf[32];
uint8_t n;
n = nrf_rcv_pkt_time(1000, 32, buf);
if( n == 32 && buf[0] == type && buf[1] == 'X' ){
for(int i=0; i<NUMWORDS*4; i++)
x[i] = buf[i+2];
n = nrf_rcv_pkt_time(100, 32, buf);
if( n == 32 && buf[0] ==type && buf[1] == 'Y' ){
for(int i=0; i<NUMWORDS*4; i++)
y[i] = buf[i+2];
return 0;
}
}
return -1;
}
int receivePublicKey(uint8_t *px, uint8_t *py)
{
return receiveKey('P',px,py);
}
void sendMac(void)
{
uint8_t buf[32];
buf[0] = 'M';
buf[1] = 'C';
buf[2] = mac[0];
buf[3] = mac[1];
buf[4] = mac[2];
buf[5] = mac[3];
buf[6] = mac[4];
nrf_snd_pkt_crc(32, buf);
delayms(10);
}
int receiveMac(uint8_t *mac)
{
uint8_t buf[32];
uint8_t n;
n = nrf_rcv_pkt_time(100, 32, buf);
if( n == 32 && buf[0] == 'M' && buf[1] == 'C' ){
for(int i=0; i<5; i++)
mac[i] = buf[i+2];
return 0;
}
return -1;
}
int receiveKeys(uint8_t *px, uint8_t *py, uint8_t *mac)
{
uint8_t done = 0;
char key;
while( !done ){
lcdClear();
lcdPrintln("Recv. PUBKEY");
lcdPrintln("Down=Abort");
lcdRefresh();
key = getInput();
delayms(20);
if( key == BTN_DOWN ){
return -1;
}
if( receivePublicKey(px,py) )
continue;
if( receiveMac(mac) )
continue;
lcdClear();
lcdPrintln("Got PUBKEY"); lcdRefresh();
lcdPrintln("Hash:");
lcdPrintln("Right=OK");
lcdPrintln("Left=Retry");
lcdPrintln("Down=Abort");
lcdRefresh();
while(1){
key = getInput();
delayms(20);
if( key == BTN_LEFT ){
break;
}else if( key == BTN_RIGHT ){
done = 1;
break;
}else if( key == BTN_DOWN ){
return -1;
}
}
}
return 0;
}
void sendFile(char *filename)
{
uint8_t px[4*NUMWORDS];
uint8_t py[4*NUMWORDS];
uint8_t mac[5];
if( receiveKeys(px, py, mac) )
return;
uint8_t done = 0;
uint8_t key;
uint8_t k1[16], k2[16], rx[4*NUMWORDS], ry[4*NUMWORDS];
lcdClear();
lcdPrintln("Creating key"); lcdRefresh();
ECIES_encyptkeygen(px, py, k1, k2, rx, ry);
while( !done ){
lcdPrintln("Sending file");lcdRefresh();
sendR(rx,ry);
delayms(3000);
filetransfer_send((uint8_t*)filename, 0, mac, (uint32_t*)k1);
lcdPrintln("Done");
lcdPrintln("Right=OK");
lcdPrintln("Left=Retry");
lcdRefresh();
while(1){
key = getInput();
delayms(20);
if( key == BTN_LEFT ){
break;
}else if( key == BTN_RIGHT ){
done = 1;
break;
}
}
lcdClear();
}
}
#include <string.h>
#include "funk/nrf24l01p.h"
#include "funk/filetransfer.h"
#include "funk/rftransfer.h"
#include "basic/basic.h"
#include "basic/xxtea.h"
#include "filesystem/ff.h"
#include "lcd/print.h"
//TODO: use a proper MAC to sign the message
int filetransfer_send(uint8_t *filename, uint16_t size,
uint8_t *mac, uint32_t const k[4])
{
uint8_t buf[MAXSIZE];
FIL file;
FRESULT res;
UINT readbytes;
if( size > MAXSIZE )
return 1; //File to big
res=f_open(&file, (const char*)filename, FA_OPEN_EXISTING|FA_READ);
if( res )
return res;
//res = f_read(&file, (char *)buf, size, &readbytes);
for(uint16_t i=0; i<MAXSIZE; i++)
buf[i] = 0;
res = f_read(&file, (char *)buf, MAXSIZE, &readbytes);
size = readbytes;
if( res )
return res;
if( size != readbytes)
return 1; //Error while reading
uint16_t wordcount = (size+3)/4;
//uint8_t macbuf[5];
uint8_t metadata[32];
if( strlen((char*)filename) < 20 )
strcpy((char*)metadata, (char*)filename);
else
return 1; //File name too long
metadata[20] = size >> 8;
metadata[21] = size & 0xFF;
//nrf_get_tx_max(5,macbuf);
//nrf_set_tx_mac(5, mac);
nrf_snd_pkt_crc_encr(32, metadata, k);
delayms(20);
xxtea_encode_words((uint32_t *)buf, wordcount, k);
rftransfer_send(wordcount*4, buf);
//nrf_set_tx_mac(5, macbuf);
return 0;
}
#include "funk/rftransfer.h"
#include "funk/nrf24l01p.h"
#include <basic/basic.h>
#include <basic/random.h>
#include <core/systick/systick.h>
#include <lcd/print.h>
#define MAXPACKET 32
void rftransfer_send(uint16_t size, uint8_t *data)
{
uint8_t buf[MAXPACKET];
buf[0] = 'L';
buf[1] = size >> 8;
buf[2] = size & 0xFF;
uint16_t rand = getRandom() & 0xFFFF;
buf[3] = rand >> 8;
buf[4] = rand & 0xFF;
nrf_snd_pkt_crc(32,buf); //setup packet
delayms(20);
uint16_t index = 0;
uint8_t i;
uint16_t crc = crc16(data,size);
while(size){
buf[0] = 'D';
buf[1] = index >> 8;
buf[2] = index & 0xFF;
buf[3] = rand >> 8;
buf[4] = rand & 0xFF;
for(i=5; i<MAXPACKET-2 && size>0; i++,size--){
buf[i] = *data++;
}
index++;
nrf_snd_pkt_crc(32,buf); //data packet
delayms(20);
}
buf[0] = 'C';
buf[1] = crc >> 8;
buf[2] = crc & 0xFF;
buf[3] = rand >> 8;
buf[4] = rand & 0xFF;
nrf_snd_pkt_crc(32,buf); //setup packet
delayms(20);
}

View File

@ -1,462 +0,0 @@
#include <sysinit.h>
#include <string.h>
#include "basic/basic.h"
#include "basic/random.h"
#include "lcd/render.h"
#include "lcd/display.h"
#include "lcd/allfonts.h"
/**************************************************************************/
#define POS_PLAYER_Y 60
#define POS_PLAYER_X RESX/2-3
#define POS_UFO_Y 0
#define ENEMY_ROWS 3
#define ENEMY_COLUMNS 6
#define DISABLED 255
#define UFO_PROB 1024
#define TYPE_PLAYER 1
#define TYPE_ENEMY_A 3
#define TYPE_ENEMY_B 2
#define TYPE_ENEMY_C 4
#define TYPE_UFO 5
#define BUNKERS 3
#define BUNKER_WIDTH 10
static const uint8_t BUNKER_X[] = {15, RESX/2-BUNKER_WIDTH/2,RESX-BUNKER_WIDTH-15};
static const uint8_t ENEMY_WIDTHS[] = {8,10,12};
struct gamestate {
char player;
char ufo;
char shot_x, shot_y;
char shots_x[ENEMY_COLUMNS];
char shots_y[ENEMY_COLUMNS];
char alive;
int16_t move;
char direction, lastcol;
bool killed;
bool step;
uint32_t score;
uint16_t level;
int8_t rokets;
char enemy_x[ENEMY_ROWS][ENEMY_COLUMNS];
char enemy_row_y[ENEMY_ROWS];
uint8_t bunker[BUNKERS][BUNKER_WIDTH];
} game;
char key;
void init_game();
void init_enemy();
void check_end();
void move_ufo();
void move_shot();
void move_shots();
void move_player();
void move_enemy();
void draw_score();
void draw_bunker();
void draw_player();
void draw_enemy();
void draw_shots();
void draw_sprite(char type, char x, char y);
void draw_ufo();
void screen_intro();
void screen_gameover();
void screen_level();
bool check_bunker(char xpos, char ypos, int8_t shift);
void ram(void) {
//gpioSetValue (RB_LED1, CFG_LED_OFF);
//backlightInit();
while(1) {
screen_intro();
game.rokets = 3;
game.level = 1;
init_game();
screen_level();
while (game.rokets>=0) {
////checkISP();
lcdFill(0);
check_end();
move_ufo();
move_shot();
move_shots();
move_player();
move_enemy();
draw_score();
draw_ufo();
draw_bunker();
draw_player();
draw_enemy();
draw_shots();
// draw_status();
lcdDisplay();
delayms(12);
}
screen_gameover();
}
return;
}
void screen_intro() {
char key=0;
while(key==0) {
lcdFill(0);
font = &Font_Invaders;
DoString(28,25,"ABC");
font = &Font_7x8;
DoString (28,40,"SPACE");
DoString (18,50,"INVADERS");
//DoString (20,RESY-24, "Highscore");
DoString (0, 0, "12345");
DoString (0, 9, "iggy");
lcdDisplay();
delayms_queue(50);
key=getInput();
}
}
void screen_gameover() {
char key =0;
while(key==0) {
lcdFill(0);
font = &Font_7x8;
DoString (12,32, "GAME OVER");
DoInt (0,0, game.score);
DoString (0,9,"HIGHSCORE!");
lcdDisplay();
delayms_queue(50);
key=getInput();
}
}
void screen_level() {
lcdFill(0);
draw_score();
font = &Font_7x8;
int dx = DoString(20,32, "Level ");
DoInt(dx,32,game.level);
lcdDisplay();
delayms(500);
}
void init_game(void) {
game.player = POS_PLAYER_X;
game.shot_x = DISABLED;
game.shot_y = 0;
game.alive = ENEMY_ROWS*ENEMY_COLUMNS;
game.move = 0;
if (getRandom()%2 == 0) {
game.direction = -1;
game.lastcol = ENEMY_COLUMNS-1;
} else {
game.direction = 1;
game.lastcol = 0;
}
game.killed = 0;
game.step = false;
game.ufo = DISABLED;
game.score = 0;
init_enemy();
for (int col=0; col<ENEMY_COLUMNS; col++){
game.shots_x[col] = DISABLED;
}
for (int b=0; b<BUNKERS; b++){
//for (int slice=0; slice<BUNKER_WIDTH; slice++){
// game.bunker[b][slice] = 255<<2;
//}
game.bunker[b][0] = 0b00111100;
game.bunker[b][1] = 0b01111100;
game.bunker[b][2] = 0b11111100;
game.bunker[b][3] = 0b11100000;
game.bunker[b][4] = 0b11100000;
game.bunker[b][5] = 0b11100000;
game.bunker[b][6] = 0b11100000;
game.bunker[b][7] = 0b11111100;
game.bunker[b][8] = 0b01111100;
game.bunker[b][9] = 0b00111100;
}
}
void init_enemy() {
for (int row = 0; row<ENEMY_ROWS; row++) {
game.enemy_row_y[row] = 10 + (40/ENEMY_ROWS)*row;
for (int col = 0; col<ENEMY_COLUMNS; col++) {
game.enemy_x[row][col] = 5+(86/ENEMY_COLUMNS)*col+(2-row);
}
}
}
bool check_bunker(char xpos, char ypos, int8_t shift){
for (int b=0; b<BUNKERS; b++) {
if (xpos>BUNKER_X[BUNKERS-1-b] &&
xpos<BUNKER_X[BUNKERS-1-b]+BUNKER_WIDTH &&
ypos<RESY-8 &&
ypos>RESY-16) {
int offset = BUNKER_WIDTH - (xpos-BUNKER_X[BUNKERS-1-b]);
if (game.bunker[b][offset]!=0) {
if (shift>0)
game.bunker[b][offset]&=game.bunker[b][offset]<<shift;
else
game.bunker[b][offset]&=game.bunker[b][offset]>>-shift;
return true;
}
}
}
return false;
}
void move_shot() {
//No shot, do nothing
if(game.shot_x == DISABLED) {
return;
}
//moving out of top, end shot
if (game.shot_y <= 0) {
game.shot_x = DISABLED;
return;
}
if (check_bunker(game.shot_x,game.shot_y-5,1 ))
game.shot_x=DISABLED;
//check for collision with enemy, kill enemy if
for (int row=0; row<ENEMY_ROWS; row++) {
if (game.enemy_row_y[row]+6 >= game.shot_y && game.enemy_row_y[row]+6 < game.shot_y+7) {
for(int col = 0; col<ENEMY_COLUMNS; col++) {
if(game.shot_x >= game.enemy_x[row][col] && game.shot_x < game.enemy_x[row][col]+ENEMY_WIDTHS[row]) {
game.enemy_x[row][col]=DISABLED;
game.shot_x = DISABLED;
game.alive--;
game.score+=(3-row)*10;
return;
}
}
}
}
//check for collision with ufo
if (game.ufo != DISABLED &&
game.shot_x>game.ufo &&
game.shot_x<game.ufo + 16 &&
game.shot_y<8) {
game.ufo = DISABLED;
game.score += 50;
}
game.shot_y -= 2;
}
void move_shots() {
for (int col = 0; col<ENEMY_COLUMNS; col++){
//No shot, maybe generate
if (game.shots_x[col] == DISABLED) {
for (int row = 0; row<ENEMY_ROWS; row++) {
if (game.enemy_x[row][col] != DISABLED) {
if(getRandom()%(game.alive*20/((game.level/3)+1))==0) {
game.shots_x[col] = game.enemy_x[row][col]+5;
game.shots_y[col] = game.enemy_row_y[row]+0;
}
}
}
continue;
}
//moving out of bottm, end shot
if (game.shots_y[col] >= RESY) {
game.shots_x[col] = DISABLED;
return;
}
//check for collision with bunker
if (check_bunker(game.shots_x[col],game.shots_y[col],-1))
game.shots_x[col]=DISABLED;
//check for collision with player
if (game.shots_y[col] >= RESY-13 &&
game.shots_x[col] > game.player+1 &&
game.shots_x[col] < game.player+6) {
game.killed = true;
}
//move shots down
game.shots_y[col] += 1;
}
}
void move_ufo() {
if (game.ufo == DISABLED) {
if ((getRandom()%UFO_PROB)==0) {
game.ufo = 0;
}
return;
}
if (game.ufo >= RESX){
game.ufo = DISABLED;
return;
}
game.ufo++;
}
void move_player() {
if(gpioGetValue(RB_BTN0)==0 && game.player > 0 ){
game.player-=1;
}
if(gpioGetValue(RB_BTN1)==0 && game.player < RESX-8){
game.player+=1;
}
if(gpioGetValue(RB_BTN4)==0 && game.shot_x == 255){
game.shot_x = game.player+4;
game.shot_y = POS_PLAYER_Y;
}
}
void move_enemy() {
if(game.move > 0){
game.move-=game.level/5+1;
return;
}
game.step = !game.step;
for (int col = 0; col < ENEMY_COLUMNS; col++) {
for (int row = 0; row < ENEMY_ROWS; row++) {
char pos = game.enemy_x[row][(game.direction==1)?(ENEMY_COLUMNS-(col+1)):col];
if (pos != DISABLED) {
//Check collision with player
if((game.enemy_row_y[row]+8 >= POS_PLAYER_Y && pos+8 >= game.player && pos < game.player+8) ||
game.enemy_row_y[row]+8 >= POS_PLAYER_Y+8) {
for(int row=0; row<ENEMY_ROWS; row++) {
game.enemy_row_y[row] = 10 + (40/ENEMY_ROWS)*row;
}
game.killed = true;
}
check_bunker(pos,game.enemy_row_y[row]+8,-2);
//Are we at the beginning or end? Direction change
if((pos <=0 && game.direction != 1) ||
(pos >=RESX-10 && game.direction == 1)){
game.direction = (game.direction==1)?-1:1;
for (int r = 0; r<ENEMY_ROWS; r++) {
game.enemy_row_y[r]+=game.level>=23?4:2;
}
return;
}
game.enemy_x[row][(game.direction==1)?(ENEMY_COLUMNS-(col+1)):col] += game.direction;
}
}
}
game.move = game.alive*2-1;
}
void draw_player() {
draw_sprite(TYPE_PLAYER, game.player, POS_PLAYER_Y);
}
void draw_ufo() {
if (game.ufo!=DISABLED)
draw_sprite(TYPE_UFO, game.ufo, POS_UFO_Y);
}
void draw_enemy() {
for (int row = 0; row<ENEMY_ROWS; row++) {
for (int col = 0; col<ENEMY_COLUMNS; col++) {
if (game.enemy_x[row][col] != DISABLED) {
draw_sprite(TYPE_ENEMY_C-row,game.enemy_x[row][col],game.enemy_row_y[row]);
}
}
}
}
void draw_bunker() {
for (int b=0; b<BUNKERS; b++) {
memcpy(lcdBuffer+(RESX*1+BUNKER_X[b]),game.bunker+b,BUNKER_WIDTH);
}
}
void draw_shots() {
if (game.shot_x != 255) {
for (int length=0; length<=5; length++) {
lcdSetPixel(game.shot_x, game.shot_y+length, true);
}
}
for (int col = 0; col < ENEMY_COLUMNS; col++) {
if (game.shots_x[col] != DISABLED) {
for (int length=0; length<=5; length++) {
lcdSetPixel(game.shots_x[col], game.shots_y[col]+length,true);
}
}
}
}
void draw_status() {
for (int p = 0; p<game.alive; p++){
lcdSetPixel(p+1,1,true);
}
}
void draw_sprite(char type, char x, char y) {
font = &Font_Invaders;
switch(type) {
case TYPE_PLAYER:
DoChar(x,y-1,'P');
break;
case TYPE_ENEMY_A:
DoChar(x,y-1,game.step?'a':'A');
break;
case TYPE_ENEMY_B:
DoChar(x,y-1,game.step?'b':'B');
break;
case TYPE_ENEMY_C:
DoChar(x,y-1,game.step?'c':'C');
break;
case TYPE_UFO:
DoChar(x,y-1,'U');
break;
}
}
void draw_score() {
font = &Font_7x8;
DoInt(0,0,game.score);
DoInt(RESX-8,0,game.rokets);
font = &Font_Invaders;
DoChar(RESX-16, 0, 'P');
}
void check_end() {
if (game.killed) {
game.rokets--;
delayms(500);
game.player = POS_PLAYER_X;
for(int col=0; col<ENEMY_COLUMNS; col++) {
game.shots_x[col] = DISABLED;
}
game.killed = false;
}
if (game.alive == 0) {
delayms(500);
game.level++;
init_game();
screen_level();
}
}

View File

@ -37,9 +37,11 @@ SECTIONS
{
KEEP(*(.irq_vectors))
KEEP(*(table))
*(.text.main)
. = 0x000002FC ; /* or 1FC for LPC2000 */
/* or 1FC for LPC2000*/
/* *(.text.main)
. = 0x000002FC ;
KEEP(*(crp))
*/
*(.text*)
*(.rodata*)
} > flash

View File

@ -28,7 +28,7 @@
#define CRP_VALUE 0x0 // ANY non-magic value disables CRP
#endif
__attribute__ ((used, section("crp"))) const uint32_t the_crp=CRP_VALUE;
//__attribute__ ((used, section("crp"))) const uint32_t the_crp=CRP_VALUE;
/**************************************************************************/

View File

@ -4,7 +4,6 @@
OBJS =
OBJS += cdcuser.o
OBJS += cdc_buf.o
OBJS += usbcore.o
OBJS += usbdesc.o
OBJS += usbhw.o

View File

@ -1,161 +0,0 @@
/*******************************************************************
Copyright (C) 2009 FreakLabs
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 the the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE THE COPYRIGHT HOLDERS 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 THE INSTITUTE OR 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.
Originally written by Christopher Wang aka Akiba.
Please post support questions to the FreakLabs forum.
*******************************************************************/
/**************************************************************************/
/*!
@file cdc_buf.c
@author Christopher Wang (Freaklabs)
Modified by: K. Townsend (microBuilder.eu)
@date 19 May 2010
Original code taken from the FreakUSB Open Source USB Device Stack
http://freaklabs.org/index.php/FreakUSB-Open-Source-USB-Device-Stack.html
If it works well, you can thank Akiba at Freaklabs. If it fails
miserably, you can blame me (since parts of it it were rather
ungraciously modified). :-)
*/
/**************************************************************************/
#include "cdc_buf.h"
static cdc_buffer_t cdcfifo;
/**************************************************************************/
/*!
Gets a pointer to the fifo buffer
*/
/**************************************************************************/
cdc_buffer_t *cdcGetBuffer()
{
return &cdcfifo;
}
/**************************************************************************/
/*!
Initialises the RX FIFO buffer
*/
/**************************************************************************/
void cdcBufferInit()
{
cdcfifo.len = 0;
}
/**************************************************************************/
/*!
Read one byte out of the RX buffer. This function will return the byte
located at the array index of the read pointer, and then increment the
read pointer index. If the read pointer exceeds the maximum buffer
size, it will roll over to zero.
*/
/**************************************************************************/
uint8_t cdcBufferRead()
{
uint8_t data;
data = cdcfifo.buf[cdcfifo.rd_ptr];
cdcfifo.rd_ptr = (cdcfifo.rd_ptr + 1) % CFG_USBCDC_BUFFERSIZE;
cdcfifo.len--;
return data;
}
/**************************************************************************/
/*!
Reads x bytes from cdc buffer
*/
/**************************************************************************/
uint32_t cdcBufferReadLen(uint8_t* buf, uint32_t len)
{
uint32_t counter, actual;
counter = actual = 0;
while(counter != len)
{
// Make sure we don't exceed buffer limits
if (cdcfifo.len > 0)
{
buf[counter] = cdcBufferRead();
actual++;
counter++;
}
else
{
return actual;
}
}
return actual;
}
/**************************************************************************/
/*!
Write one byte into the RX buffer. This function will write one
byte into the array index specified by the write pointer and increment
the write index. If the write index exceeds the max buffer size, then it
will roll over to zero.
*/
/**************************************************************************/
void cdcBufferWrite(uint8_t data)
{
cdcfifo.buf[cdcfifo.wr_ptr] = data;
cdcfifo.wr_ptr = (cdcfifo.wr_ptr + 1) % CFG_USBCDC_BUFFERSIZE;
cdcfifo.len++;
}
/**************************************************************************/
/*!
Clear the fifo read and write pointers and set the length to zero.
*/
/**************************************************************************/
void cdcBufferClearFIFO()
{
cdcfifo.rd_ptr = 0;
cdcfifo.wr_ptr = 0;
cdcfifo.len = 0;
}
/**************************************************************************/
/*!
Check whether there is any data pending on the RX buffer.
*/
/**************************************************************************/
uint8_t cdcBufferDataPending()
{
if (cdcfifo.len != 0)
{
return 1;
}
return 0;
}

View File

@ -1,29 +0,0 @@
/*----------------------------------------------------------------------------
* Name: cdc_buf.h
* Purpose: usb cdc buffer handling
* Version: V1.00
*---------------------------------------------------------------------------*/
#ifndef __CDC_BUF_H__
#define __CDC_BUF_H__
#include "projectconfig.h"
// Buffer used for circular fifo
typedef struct _cdc_buffer_t
{
volatile uint8_t len;
volatile uint8_t wr_ptr;
volatile uint8_t rd_ptr;
uint8_t buf[CFG_USBCDC_BUFFERSIZE];
} cdc_buffer_t;
cdc_buffer_t * cdcGetBuffer();
void cdcBufferInit();
uint8_t cdcBufferRead();
uint32_t cdcBufferReadLen(uint8_t* buf, uint32_t len);
void cdcBufferWrite(uint8_t data);
void cdcBufferClearFIFO();
uint8_t cdcBufferDataPending();
#endif

View File

@ -1,4 +1,4 @@
/*----------------------------------------------------------------------------
/*----------/BulkBufOut------------------------------------------------------------------
* U S B - K e r n e l
*----------------------------------------------------------------------------
* Name: cdcuser.c
@ -17,6 +17,7 @@
*---------------------------------------------------------------------------*/
#include "projectconfig.h"
#include "basic/basic.h"
#include "usb.h"
#include "usbhw.h"
@ -24,15 +25,16 @@
#include "usbcore.h"
#include "cdc.h"
#include "cdcuser.h"
#include "cdc_buf.h"
#include "usbreg.h"
// unsigned char BulkBufIn [64]; // Buffer to store USB IN packet
unsigned char BulkBufIn [64]; // Buffer to store USB IN packet
unsigned char BulkBufOut [64]; // Buffer to store USB OUT packet
unsigned char NotificationBuf [10];
CDC_LINE_CODING CDC_LineCoding = {CFG_USBCDC_BAUDRATE, 0, 0, 8};
unsigned short CDC_SerialState = 0x0000;
unsigned short CDC_DepInEmpty = 1; // Data IN EP is empty
volatile unsigned char CDC_DepInEmpty = 1; // Data IN EP is empty
/*----------------------------------------------------------------------------
We need a buffer for incoming data on USB port because USB receives
@ -61,6 +63,7 @@ typedef struct __CDC_BUF_T
} CDC_BUF_T;
CDC_BUF_T CDC_OutBuf; // buffer for all CDC Out data
CDC_BUF_T CDC_InBuf; // buffer for all CDC Out data
/*----------------------------------------------------------------------------
read data from CDC_OutBuf
@ -116,6 +119,71 @@ int CDC_OutBufAvailChar (int *availChar)
}
/* end Buffer handling */
/*----------------------------------------------------------------------------
read data from CDC_InBuf
*---------------------------------------------------------------------------*/
int CDC_RdInBuf (char *buffer, const int *length)
{
int bytesToRead, bytesRead;
/* Read *length bytes, block if *bytes are not avaialable */
bytesToRead = *length;
//bytesToRead = (bytesToRead < (*length)) ? bytesToRead : (*length);
bytesRead = bytesToRead;
// ... add code to check for underrun
while (bytesToRead--) {
*buffer++ = CDC_BUF_RD(CDC_InBuf);
}
return (bytesRead);
}
/*----------------------------------------------------------------------------
write data to CDC_InBuf
*---------------------------------------------------------------------------*/
int CDC_WrInBuf (const char *buffer, int *length)
{
int bytesToWrite, bytesWritten;
// Write *length bytes
bytesToWrite = *length;
bytesWritten = bytesToWrite;
// Just block if we can't write all at once
// +1 to prevent an overflow of the ring buffer
while( CDC_BUF_SIZE - CDC_BUF_COUNT(CDC_InBuf) < bytesToWrite+1 );
//uint8_t flush = CDC_DepInEmpty;
USB_DEVINTEN = 0;
while (bytesToWrite--) {
CDC_BUF_WR(CDC_InBuf, *buffer++); // Copy Data to buffer
}
//if( flush == 1 ){
//if( CDC_DepInEmpty && CDC_BUF_COUNT(CDC_InBuf) ){
if( CDC_DepInEmpty ){
CDC_DepInEmpty = 0;
CDC_BulkIn();
}
USB_DEVINTEN = DEV_STAT_INT | (0xFF<<1) | (USB_SOF_EVENT ? FRAME_INT : 0);
return (bytesWritten);
}
/*----------------------------------------------------------------------------
check if character(s) are available at CDC_OutBuf
*---------------------------------------------------------------------------*/
int CDC_InBufAvailChar (int *availChar)
{
*availChar = CDC_BUF_COUNT(CDC_InBuf);
return (0);
}
/* end Buffer handling */
/*----------------------------------------------------------------------------
CDC Initialisation
@ -129,12 +197,8 @@ void CDC_Init (void)
CDC_SerialState = CDC_GetSerialState();
CDC_BUF_RESET(CDC_OutBuf);
CDC_BUF_RESET(CDC_InBuf);
// Initialise the CDC buffer. This is required to buffer outgoing
// data (MCU to PC) since data can only be sent 64 bytes per frame
// with at least 1ms between frames. To see how the buffer is used,
// see 'puts' in systeminit.c
cdcBufferInit();
}
@ -269,7 +333,6 @@ uint32_t CDC_SendBreak (unsigned short wDurationOfBreak) {
return (TRUE);
}
/*----------------------------------------------------------------------------
CDC_BulkIn call on DataIn Request
Parameters: none
@ -277,25 +340,19 @@ uint32_t CDC_SendBreak (unsigned short wDurationOfBreak) {
*---------------------------------------------------------------------------*/
void CDC_BulkIn(void)
{
// int numBytesRead, numBytesAvail;
//
// // ToDo: Modify BulkIn to send incoming data to USB
//
// ser_AvailChar (&numBytesAvail);
//
// // ... add code to check for overwrite
//
// numBytesRead = ser_Read ((char *)&BulkBufIn[0], &numBytesAvail);
//
// // send over USB
// if (numBytesRead > 0) {
// USB_WriteEP (CDC_DEP_IN, &BulkBufIn[0], numBytesRead);
// }
// else {
// CDC_DepInEmpty = 1;
// }
//
//
int numBytesRead, numBytesAvail;
CDC_InBufAvailChar(&numBytesAvail);
numBytesRead = CDC_RdInBuf((char*)&BulkBufIn[0], &numBytesAvail);
// send over USB
if (numBytesRead > 0) {
//gpioSetValue (RB_LED0, 1);
USB_WriteEP (CDC_DEP_IN, &BulkBufIn[0], numBytesRead);
//gpioSetValue (RB_LED0, 0);
} else {
//USB_WriteEP (CDC_DEP_IN, "test\r\n", 6);
CDC_DepInEmpty = 1;
//gpioSetValue (RB_LED2, 1);
}
}

View File

@ -24,6 +24,7 @@ extern int CDC_RdOutBuf (char *buffer, const int *length);
extern int CDC_WrOutBuf (const char *buffer, int *length);
extern int CDC_OutBufAvailChar (int *availChar);
extern int CDC_WrInBuf (const char *buffer, int *length);
/* CDC Data In/Out Endpoint Address */
#define CDC_DEP_IN 0x83
@ -57,7 +58,7 @@ extern void CDC_Init (void);
extern unsigned short CDC_GetSerialState (void);
/* flow control */
extern unsigned short CDC_DepInEmpty; // DataEndPoint IN empty
extern volatile unsigned char CDC_DepInEmpty; // DataEndPoint IN empty
#endif /* __CDCUSER_H__ */

View File

@ -26,6 +26,7 @@
#include "usbhw.h"
#include "usbcore.h"
#include "usbuser.h"
#include "basic/basic.h"
#include "usb/usbmsc.h"
@ -471,6 +472,10 @@ uint32_t USB_WriteEP (uint32_t EPNum, uint8_t *pData, uint32_t cnt)
{
uint32_t n;
//this seems rather brutal...
//disable all usb related interrupts or WrCmd might block
USB_DEVINTEN = 0;
USB_CTRL = ((EPNum & 0x0F) << 2) | CTRL_WR_EN;
/* 3 clock cycles to fetch the packet length from RAM. */
delay( 5 );
@ -486,6 +491,9 @@ uint32_t USB_WriteEP (uint32_t EPNum, uint8_t *pData, uint32_t cnt)
WrCmdEP(EPNum, CMD_VALID_BUF);
//enable interrupts again
USB_DEVINTEN = DEV_STAT_INT | (0xFF<<1) | (USB_SOF_EVENT ? FRAME_INT : 0);
return (cnt);
}

View File

@ -1,4 +1,5 @@
#include <sysinit.h>
#include <string.h>
#include "usbcdc/usb.h"
#include "usbcdc/usbcore.h"
@ -6,54 +7,20 @@
#include "usbcdc/usbhw.h"
#include "usbcdc/cdcuser.h"
#include "basic/basic.h"
volatile unsigned int lastTick;
// There must be at least 1ms between USB frames (of up to 64 bytes)
// This buffers all data and writes it out from the buffer one frame
// and one millisecond at a time
int puts(const char * str){
if(!USB_Configuration)
return -1;
while(*str)
cdcBufferWrite(*str++);
//XXX: This assumes systick is 1ms, which it isn't for us.
// this makes usbserial unnecessary slow. Ah well....
// Check if we can flush the buffer now or if we need to wait
unsigned int currentTick = systickGetTicks();
if (currentTick != lastTick){
uint8_t frame[64];
uint32_t bytesRead = 0;
char repeat=0;
while (cdcBufferDataPending()){
// Read up to 64 bytes as long as possible
bytesRead = cdcBufferReadLen(frame, 64);
USB_WriteEP (CDC_DEP_IN, frame, bytesRead);
if(repeat)
systickDelay(1);
else
repeat=1;
}
lastTick = currentTick;
}
int len = strlen(str);
CDC_WrInBuf(str, &len);
return 0;
}
int puts_plus(const char * str){
if(!USB_Configuration)
return -1;
while(*str)
cdcBufferWrite(*str++);
return 0;
return puts(str);
}
void usbCDCInit(){
lastTick = systickGetTicks(); // Used to control output/printf timing
CDC_Init(); // Initialise VCOM
USB_Init(); // USB Initialization
USB_Connect(TRUE); // USB Connect

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

122
tools/game/py-pong/main.py Normal file
View File

@ -0,0 +1,122 @@
import pygame, pypong
from pypong.player import BasicAIPlayer, KeyboardPlayer, MousePlayer, Rem0tePlayer
import r0ketrem0te.game
import time
class Pong:
def __init__(self):
self.configuration = {
'screen_size': (686,488),
'paddle_image': 'assets/paddle.png',
'paddle_left_position': 84.,
'paddle_right_position': 594.,
'paddle_velocity': 6.,
'paddle_bounds': (0, 488), # This sets the upper and lower paddle boundary.The original game didn't allow the paddle to touch the edge,
'line_image': 'assets/dividing-line.png',
'ball_image': 'assets/ball.png',
'ball_velocity': 4.,
'ball_velocity_bounce_multiplier': 1.105,
'ball_velocity_max': 32.,
'score_left_position': (141, 30),
'score_right_position': (473, 30),
'digit_image': 'assets/digit_%i.png',
'sound_missed': 'assets/missed-ball.wav',
'sound_paddle': 'assets/bounce-paddle.wav',
'sound_wall': 'assets/bounce-wall.wav',
'sound': True,
}
pygame.mixer.pre_init(22050, -16, 2, 1024)
pygame.init()
self.rem0te = r0ketrem0te.game.Game('/dev/ttyACM0', "pong", 83,
81, [ord(x) for x in 'REM0T'], 2, True)
self.rem0te.registerPlayerCallback(self.playercallback)
self.player_right = Rem0tePlayer(self.rem0te)
self.player_left = Rem0tePlayer(self.rem0te)
self.stop = True
self.start = False
self.restart()
def playercallback(self, action, player):
if action == 'added':
if self.player_left.player == None:
self.player_left.player = player
elif self.player_right.player == None:
self.player_right.player = player
if self.player_left.player and self.player_right.player:
self.start = True
elif action == 'removed':
print 'got remove for', player.nick
if self.player_left.player == player:
print 'removing left player'
self.player_left.player = None
elif self.player_right.player == player:
print 'removing right player'
self.player_right.player = None
if self.player_left.player == None or self.player_right.player == None:
print 'halting game'
self.stop = True
def restart(self):
self.display_surface = pygame.display.set_mode(self.configuration['screen_size'])
self.output_surface = self.display_surface.copy().convert_alpha()
self.output_surface.fill((0,0,0))
#~ debug_surface = output_surface.copy()
#~ debug_surface.fill((0,0,0,0))
self.debug_surface = None
self.clock = pygame.time.Clock()
self.input_state = {'key': None, 'mouse': None}
# Prepare game
self.game = pypong.Game(self.player_left, self.player_right, self.configuration)
def run(self):
# Main game loop
timestamp = 1
while self.game.running:
if self.start:
self.restart()
self.start = False
self.stop = False
self.clock.tick(60)
now = pygame.time.get_ticks()
if timestamp > 0 and timestamp < now:
timestamp = now + 5000
print self.clock.get_fps()
self.input_state['key'] = pygame.key.get_pressed()
self.input_state['mouse'] = pygame.mouse.get_pos()
if not self.stop:
self.game.update()
self.game.draw(self.output_surface)
#~ pygame.surfarray.pixels_alpha(output_surface)[:,::2] = 12
self.display_surface.blit(self.output_surface, (0,0))
font = pygame.font.Font(None, 36)
if self.player_left.player:
text = font.render(self.player_left.player.nick, 1, (0, 255, 0))
textpos = text.get_rect(centerx=self.output_surface.get_width()/4)
self.display_surface.blit(text, textpos)
if self.player_right.player:
text = font.render(self.player_right.player.nick, 1, (0, 255, 0))
textpos = text.get_rect(centerx=self.output_surface.get_width()/4*3)
self.display_surface.blit(text, textpos)
if self.debug_surface:
self.display_surface.blit(self.debug_surface, (0,0))
pygame.display.flip()
for event in pygame.event.get():
if event.type == pygame.QUIT:
self.game.running = False
elif event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE:
self.game.running = False
if __name__ == '__main__':
pong = Pong()
pong.run()

View File

@ -0,0 +1,150 @@
import pygame, math, random, entity
def load_image(path):
surface = pygame.image.load(path)
surface.convert()
pygame.surfarray.pixels3d(surface)[:,:,0:1:] = 0
return surface
def line_line_intersect(x1, y1, x2, y2, x3, y3, x4, y4):
# Taken from http://paulbourke.net/geometry/lineline2d/
# Denominator for ua and ub are the same, so store this calculation
d = float((y4 - y3) * (x2 - x1) - (x4 - x3) * (y2 - y1))
# n_a and n_b are calculated as seperate values for readability
n_a = float((x4 - x3) * (y1 - y3) - (y4 - y3) * (x1 - x3))
n_b = float((x2 - x1) * (y1 - y3) - (y2 - y1) * (x1 - x3))
# Make sure there is not a division by zero - this also indicates that
# the lines are parallel.
# If n_a and n_b were both equal to zero the lines would be on top of each
# other (coincidental). This check is not done because it is not
# necessary for this implementation (the parallel check accounts for this).
if d == 0:
return False
# Calculate the intermediate fractional point that the lines potentially intersect.
ua = n_a / d
ub = n_b / d
# The fractional point will be between 0 and 1 inclusive if the lines
# intersect. If the fractional calculation is larger than 1 or smaller
# than 0 the lines would need to be longer to intersect.
if ua >= 0. and ua <= 1. and ub >= 0. and ub <= 1.:
return [x1 + (ua * (x2 - x1)), y1 + (ua * (y2 - y1))]
return False
class Game(object):
def __init__(self, player_left, player_right, configuration):
self.player_left = player_left
self.player_right = player_right
self.configuration = configuration
self.background = pygame.Surface(configuration['screen_size'])
self.sprites = pygame.sprite.OrderedUpdates()
line = entity.Line(load_image(configuration['line_image']), self.sprites)
line.rect.topleft = ((configuration['screen_size'][0]-line.rect.width)/2, 0)
paddle_image = load_image(configuration['paddle_image'])
self.paddle_left = entity.Paddle(configuration['paddle_velocity'], paddle_image, configuration['paddle_bounds'], self.sprites)
self.paddle_right = entity.Paddle(configuration['paddle_velocity'], paddle_image, configuration['paddle_bounds'], self.sprites)
self.paddle_left.rect.topleft = (self.configuration['paddle_left_position'], (self.configuration['screen_size'][1]-self.paddle_left.rect.height)/2)
self.paddle_right.rect.topleft = (self.configuration['paddle_right_position'], (self.configuration['screen_size'][1]-self.paddle_left.rect.height)/2)
digit_images = [load_image(configuration['digit_image'] % n) for n in xrange(10)]
self.score_left = entity.Score(digit_images, self.sprites)
self.score_left.rect.topleft = configuration['score_left_position']
self.score_right = entity.Score(digit_images, self.sprites)
self.score_right.rect.topleft = configuration['score_right_position']
ball_image = load_image(configuration['ball_image'])
self.ball = entity.Ball(self.configuration['ball_velocity'], ball_image, self.sprites)
self.bounds = pygame.Rect(20, 0, configuration['screen_size'][0]-ball_image.get_width()-20, configuration['screen_size'][1]-ball_image.get_height())
self.sound_missed = pygame.mixer.Sound(configuration['sound_missed'])
self.sound_paddle = pygame.mixer.Sound(configuration['sound_paddle'])
self.sound_wall = pygame.mixer.Sound(configuration['sound_wall'])
self.reset_game(random.random()<0.5)
self.running = True
def play_sound(self, sound):
if self.configuration['sound']:
sound.play()
def reset_game(self, serveLeft=True):
y = self.configuration['screen_size'][1] - self.ball.rect.height
self.ball.position_x = (self.configuration['screen_size'][0]-self.ball.rect.width)/2.0
self.ball.position_y = y * random.random()
self.ball.velocity = self.configuration['ball_velocity']
a = random.random() * math.pi / 2. - math.pi / 4.
self.ball.velocity_vec[0] = self.ball.velocity * math.cos(a)
self.ball.velocity_vec[1] = self.ball.velocity * math.sin(a)
if random.random() < 0.5:
self.ball.velocity_vec[1] = -self.ball.velocity_vec[1]
if serveLeft:
self.ball.velocity_vec[0] *= -1
def update(self):
# Store previous ball position for line-line intersect test later
ball_position_x = self.ball.position_x
ball_position_y = self.ball.position_y
# Update sprites and players
self.sprites.update()
self.player_left.update(self.paddle_left, self)
self.player_right.update(self.paddle_right, self)
# Paddle collision check. Could probably just do a line-line intersect but I think I prefer having the pixel-pefect result of a rect-rect intersect test as well.
if self.ball.rect.x < self.bounds.centerx:
# Left side bullet-through-paper check on ball and paddle
if self.ball.velocity_vec[0] < 0:
intersect_point = line_line_intersect(
self.paddle_left.rect.right, self.paddle_left.rect.top,
self.paddle_left.rect.right, self.paddle_left.rect.bottom,
ball_position_x-self.ball.rect.width/2, ball_position_y+self.ball.rect.height/2,
self.ball.position_x-self.ball.rect.width/2, self.ball.position_y+self.ball.rect.height/2
)
if intersect_point:
self.ball.position_y = intersect_point[1]-self.ball.rect.height/2
if intersect_point or (self.paddle_left.rect.colliderect(self.ball.rect) and self.ball.rect.right > self.paddle_left.rect.right):
self.ball.position_x = self.paddle_left.rect.right
velocity = self.paddle_left.calculate_bounce(min(1,max(0,(self.ball.rect.centery - self.paddle_left.rect.y)/float(self.paddle_left.rect.height))))
self.ball.velocity = min(self.configuration['ball_velocity_max'], self.ball.velocity * self.configuration['ball_velocity_bounce_multiplier'])
self.ball.velocity_vec[0] = velocity[0] * self.ball.velocity
self.ball.velocity_vec[1] = velocity[1] * self.ball.velocity
self.player_left.hit()
self.play_sound(self.sound_paddle)
else:
# Right side bullet-through-paper check on ball and paddle.
if self.ball.velocity_vec[0] > 0:
intersect_point = line_line_intersect(
self.paddle_right.rect.left, self.paddle_right.rect.top,
self.paddle_right.rect.left, self.paddle_right.rect.bottom,
ball_position_x-self.ball.rect.width/2, ball_position_y+self.ball.rect.height/2,
self.ball.position_x-self.ball.rect.width/2, self.ball.position_y+self.ball.rect.height/2
)
if intersect_point:
self.ball.position_y = intersect_point[1]-self.ball.rect.height/2
if intersect_point or (self.paddle_right.rect.colliderect(self.ball.rect) and self.ball.rect.x < self.paddle_right.rect.x):
self.ball.position_x = self.paddle_right.rect.x - self.ball.rect.width
velocity = self.paddle_right.calculate_bounce(min(1,max(0,(self.ball.rect.centery - self.paddle_right.rect.y)/float(self.paddle_right.rect.height))))
self.ball.velocity = min(self.configuration['ball_velocity_max'], self.ball.velocity * self.configuration['ball_velocity_bounce_multiplier'])
self.ball.velocity_vec[0] = -velocity[0] * self.ball.velocity
self.ball.velocity_vec[1] = velocity[1] * self.ball.velocity
self.player_right.hit()
self.play_sound(self.sound_paddle)
# Bounds collision check
if self.ball.rect.y < self.bounds.top:
self.ball.position_y = float(self.bounds.top)
self.ball.velocity_vec[1] = -self.ball.velocity_vec[1]
self.play_sound(self.sound_wall)
elif self.ball.rect.y > self.bounds.bottom:
self.ball.position_y = float(self.bounds.bottom)
self.ball.velocity_vec[1] = -self.ball.velocity_vec[1]
self.play_sound(self.sound_wall)
# Check the ball is still in play
if self.ball.rect.x < self.bounds.x:
self.player_left.lost()
self.player_right.won()
self.score_right.score += 1
self.reset_game(False)
self.play_sound(self.sound_missed)
if self.ball.rect.x > self.bounds.right:
self.player_left.won()
self.player_right.lost()
self.score_left.score += 1
self.reset_game(True)
self.play_sound(self.sound_missed)
def draw(self, display_surface):
self.sprites.clear(display_surface, self.background)
return self.sprites.draw(display_surface)

View File

@ -0,0 +1,87 @@
import pygame, math
from pygame.sprite import Sprite
class Paddle(Sprite):
def __init__(self, velocity, image, bounds_y, *groups):
Sprite.__init__(self, *groups)
self.image = image
self.rect = self.image.get_rect()
self.direction = 0
self.velocity = velocity
self.bounds_y = bounds_y
# Like original pong, we break this up into 8 segments from the edge angle (acute_angle) to pi/2 at the center
# Changing acute_angle lets us change the extreme edge angle of the paddle.
acute_angle = .125
# Build the angles from acute_angle to the first 0.5 center value then append the values going from the
# second center 0.5 value by using the values we just calculated reversed.
angles = [acute_angle + (0.5-acute_angle)/3.0 * n for n in xrange(4)]
angles += map(lambda x: 1 + x * -1, reversed(angles))
# Final table is the output vector (x,y) of each angle
self.bounce_table = [(math.cos(n*math.pi-math.pi/2.0), math.sin(n*math.pi-math.pi/2.0)) for n in angles]
def update(self):
self.rect.y = max(self.bounds_y[0], min(self.bounds_y[1]-self.rect.height, self.rect.y + self.direction * self.velocity))
def calculate_bounce(self, delta):
return self.bounce_table[int(round(delta * (len(self.bounce_table)-1)))]
class Line(Sprite):
def __init__(self, image, *groups):
Sprite.__init__(self, *groups)
self.image = image
self.rect = self.image.get_rect()
class Ball(Sprite):
def __init__(self, velocity, image, *groups):
Sprite.__init__(self, *groups)
self.velocity = velocity
self.image = image
self.rect = self.image.get_rect()
self.position_vec = [0., 0.]
self.velocity_vec = [0., 0.]
def update(self):
self.position_vec[0] += self.velocity_vec[0]
self.position_vec[1] += self.velocity_vec[1]
self.rect.x = self.position_vec[0]
self.rect.y = self.position_vec[1]
def set_position_x(self, value):
self.position_vec[0] = value
self.rect.left = value
position_x = property(lambda self: self.position_vec[0], set_position_x)
def set_position_y(self, value):
self.position_vec[1] = value
self.rect.top = value
position_y = property(lambda self: self.position_vec[1], set_position_y)
class Score(Sprite):
def __init__(self, image_list, *groups):
Sprite.__init__(self, *groups)
self.image_list = image_list
self.image = None
self.rect = pygame.Rect(0,0,0,0)
self.score = 0
def get_score(self):
return self.score_value
def set_score(self, value):
self.score_value = value
digit_spacing = 8
digit_width = self.image_list[0].get_width()
digit_height = self.image_list[0].get_height()
values = map(int, reversed(str(self.score_value)))
surface_width = len(values) * digit_width + (len(values)-1) * digit_spacing
if not self.image or self.image.get_width() < surface_width:
self.image = pygame.Surface((surface_width, digit_height))
self.image.fill((0,0,0))
self.rect.width = self.image.get_width()
self.rect.height = self.image.get_height()
offset = self.image.get_width()-digit_width
for i in values:
self.image.blit(self.image_list[i], (offset, 0))
offset = offset - (digit_width + digit_spacing)
score = property(get_score, set_score)

View File

@ -0,0 +1,118 @@
import pygame, random
import r0ketrem0te.game
import r0ketrem0te.bridge
import r0ketrem0te.packets
import time
import Queue
import threading
class Rem0tePlayer(object):
def __init__(self, rem0te):
self.rem0te = rem0te
self.rem0te.bridge.registerCallback(self.receivedPacket)
self.state = 0
self.player = None
def receivedPacket(self, packet):
if self.player == None:
return
if packet.id == self.player.id:
if isinstance(packet, r0ketrem0te.packets.Button):
self.state = packet.button
def update(self, paddle, game):
if self.state == 1:
paddle.direction = -1
elif self.state == 2:
paddle.direction = 1
else:
paddle.direction = 0
def hit(self):
pass
def lost(self):
pass
def won(self):
pass
class BasicAIPlayer(object):
def __init__(self):
self.bias = random.random() - 0.5
self.hit_count = 0
def update(self, paddle, game):
# Dead simple AI, waits until the ball is on its side of the screen then moves the paddle to intercept.
# A bias is used to decide which edge of the paddle is going to be favored.
if (paddle.rect.x < game.bounds.centerx and game.ball.rect.x < game.bounds.centerx) or (paddle.rect.x > game.bounds.centerx and game.ball.rect.x > game.bounds.centerx):
delta = (paddle.rect.centery + self.bias * paddle.rect.height) - game.ball.rect.centery
if abs(delta) > paddle.velocity:
if delta > 0:
paddle.direction = -1
else:
paddle.direction = 1
else:
paddle.direction = 0
else:
paddle.direction = 0
def hit(self):
self.hit_count += 1
if self.hit_count > 6:
self.bias = random.random() - 0.5 # Recalculate our bias, this game is going on forever
self.hit_count = 0
def lost(self):
# If we lose, randomise the bias again
self.bias = random.random() - 0.5
def won(self):
pass
class KeyboardPlayer(object):
def __init__(self, input_state, up_key=None, down_key=None):
self.input_state = input_state
self.up_key = up_key
self.down_key = down_key
def update(self, paddle, game):
if self.input_state['key'][self.up_key]:
paddle.direction = -1
elif self.input_state['key'][self.down_key]:
paddle.direction = 1
else:
paddle.direction = 0
def hit(self):
pass
def lost(self):
pass
def won(self):
pass
class MousePlayer(object):
def __init__(self, input_state):
self.input_state = input_state
pygame.mouse.set_visible(False)
def update(self, paddle, game):
centery = paddle.rect.centery/int(paddle.velocity)
mousey = self.input_state['mouse'][1]/int(paddle.velocity)
if centery > mousey:
paddle.direction = -1
elif centery < mousey:
paddle.direction = 1
else:
paddle.direction = 0
def hit(self):
pass
def lost(self):
pass
def won(self):
pass

View File

View File

@ -0,0 +1,240 @@
import serialinterface
import threading
import Queue
import crcmod
import packets
import traceback
class QueuePacket:
def __init__(self, channel, mac, acked, packet, callback=None):
self.channel = channel
self.mac = mac
self.acked = acked
self.packet = packet
self.priority = packet.priority
self.retriesleft = 5
self.timeout = 0.1
self.timer = None
self.timedout = False
self.lock = threading.RLock()
self.isdone = False
self.callback = callback
def __cmp__(self, other):
if not isinstance(other,QueuePacket):
return 1
if self.priority < other.priority:
return -1
if self.priority > other.priority:
return 1
return 0
def valid(self):
with self.lock:
return self.retriesleft > 0 and not self.acked
def sent(self, timeoutcallback):
with self.lock:
self.timedout = False
if self.retriesleft > 0:
self.retriesleft-=1
if self.acked:
self.timeoutcallback = timeoutcallback
self.timer = threading.Timer(self.timeout, self.timercallback)
self.timer.start()
elif self.callback:
self.callback('done')
def done(self):
with self.lock:
if self.timer != None:
self.timer.cancel()
self.timer = None
self.isdone = True
if self.callback:
self.callback('done')
def timercallback(self):
with self.lock:
self.timedout = True
self.timeoutcallback(self)
if retriesleft == 0:
self.callback('timeout')
class Bridge:
def __init__(self, path2device, channel, rxmac):
self.ser = serialinterface.SerialInterface(path2device, 115200, 0)
self.free = threading.Lock()
self.queueslock = threading.Lock()
self.packets = Queue.PriorityQueue()
self.outpackets = Queue.Queue()
self.crc = crcmod.predefined.mkCrcFun('crc-ccitt-false')
self.queues = {}
self.callbacks = []
self.ctrs = {}
self.reader = threading.Thread(target = self.readerThread)
self.reader.daemon = True
self.writer = threading.Thread(target = self.writerThread)
self.writer.daemon = True
self.writer.start()
self.reader.start()
self.packetlength = None
self.txmac = None
self.rxmac = None
self.channel = None
self.gameChannel = channel
self.setPacketLength(0x20)
self.setRxMAC(rxmac)
self.setChannel(channel)
self.ctr = 0
def registerCallback(self, callback):
if callback not in self.callbacks:
self.callbacks.append(callback)
def registerQueue(self, queue):
if queue not in self.queues:
self.queues[queue] = None
def putInQueue(self, queue, qp):
if queue in self.queues:
queue.put(qp);
self.checkQueues()
def processAck(self, ack):
#find the corresponding packet in the queues
found = False
for pq in self.queues.values():
if pq.packet.id == ack.id and pq.packet.ctr == ack.ctr:
#notify it
pq.done()
found = True
#notify the queue system
if found:
self.checkQueues()
else:
print "got an ack for an unknown packet"
def packetTimeout(self, qp):
self.checkQueues()
def checkQueues(self):
with self.queueslock:
for q in self.queues:
#check if a packet has to be resent
#remove it from the packet slot if it has been resent to often
qp = self.queues[q]
if qp != None:
if qp.valid():
self.queues[q] = None
elif qp.timedout:
print "packet timed out" + qp.packet
self.outpackets.put(qp)
#check if a idle queue has a new packet in line
qp = self.queues[q]
if qp == None and not q.empty():
qp = q.get()
if not isinstance(qp.packet,packets.Ack):
self.ctr+=1
qp.packet.ctr = self.ctr
self.queues[q] = qp
self.outpackets.put(qp)
def writerThread(self):
while True:
try:
#wait until we have packets to take care of
qp = self.outpackets.get()
#send it and notify the queuepacket
self.setTxMAC(qp.mac)
self.setChannel(qp.channel)
self.sendPacket(qp.packet)
qp.sent(self.packetTimeout)
self.setChannel(self.gameChannel)
except Exception as e:
print e
traceback.print_stack()
def readerThread(self):
while True:
try:
(command, data) = self.ser.readMessage()
if command == '1':
self.newPacket(data)
elif command == '2':
self.free.release()
except Exception as e:
print e
traceback.print_stack()
def newPacket(self, data):
print "received:", list(data)
crc = self.crc(data[:-2])
if data[-2:] == chr(crc>>8) + chr(crc&0xFF):
packet = packets.fromMessage(data)
print "received:", packet
if packet == None:
return
#if packet.id in self.ctrs and self.ctrs[packet.id] == packet.ctr:
# print 'ignoring duplicate'
# return
if isinstance(packet,packets.Ack):
self.ProcessAck(packet)
else:
for callback in self.callbacks:
callback(packet)
#self.packets.put(packet)
# def gotPacket(self):
# return not self.packets.empty()
# def getPacket(self):
# return self.packets.get()
def sendPacket(self, packet):
print 'sending', packet
data = packet.toMessage()
crc = self.crc(data)
data += chr(crc>>8);
data += chr(crc&0xFF);
self.free.acquire()
#print 'sending packet: len:', len(data), 'data:', list(data)
self.ser.writeMessage('1',data);
def setPacketLength(self, length):
if length == self.packetlength:
return
self.free.acquire()
self.ser.writeMessage('6', '%c'%length)
self.packetLength = length
def setTxMAC(self, mac):
if mac == self.txmac:
return
self.free.acquire()
print "setting tx mac", mac
self.ser.writeMessage('3', ''.join([chr(x) for x in mac]))
self.txmac = mac
def setRxMAC(self, mac):
if mac == self.rxmac:
return
self.free.acquire()
print "setting rx mac", mac
self.ser.writeMessage('4', ''.join([chr(x) for x in mac]))
self.rxmac = mac
def setChannel(self, channel):
if channel == self.channel:
return
self.free.acquire()
print "setting channel", channel
self.ser.writeMessage('5', '%c'%channel)
self.channel = channel

View File

@ -0,0 +1,114 @@
import bridge
import packets
import time
import Queue
import random
import threading
class Player():
def __init__(self, id):
self.id = id
self.nick = 'anonymous'
self.timeout = 10
self.active = False
class Game:
def __init__(self, device, gameName, gameChannel, announcechannel, announcemac, maxplayer=0, askname=False):
self.gameName = gameName
self.channel = gameChannel
self.gamemac = [int(random.random()*254) for x in range(1,6)]
self.playermac = list(self.gamemac)
self.playermac[4]+=1
self.gameid = int(random.random()*(2**31))
self.bridge = bridge.Bridge(device, self.channel, self.gamemac)
self.announce = packets.Announce(self.gamemac, self.channel,
self.gameid, 0, "testgame")
self.announcequeue = Queue.Queue()
self.bridge.registerQueue(self.announcequeue)
self.announcechannel = announcechannel
self.announcemac = announcemac
self.askname = askname
self.sendAnnounce()
self.maxplayer = maxplayer
self.players = {}
self.callbacks = []
self.queue = Queue.Queue()
self.bridge.registerQueue(self.queue)
self.bridge.registerCallback(self.receivedPacket)
self.checkPlayers()
def checkPlayers(self):
if self.maxplayer > 0:
toremove = []
for id in self.players:
player = self.players[id]
player.timeout-=1
if player.timeout == 0:
toremove.append(id)
for id in toremove:
player = self.players[id]
if self.askname:
print "removing player", player.nick
else:
print "removing player", id
del self.players[id]
if player.active:
player.active = False
for callback in self.callbacks:
callback("removed", player)
self.timer = threading.Timer(1, self.checkPlayers)
self.timer.start()
def receivedPacket(self, packet):
if self.maxplayer == 0:
return
if isinstance(packet, packets.Join):
# flags = 1: join ok
# flags = 0: join not ok
flags = 0
if len(self.players) < self.maxplayer:
flags = 1
self.players[packet.id] = Player(packet.id)
ack = packets.Ack(packet.id, packet.ctr, flags)
qp = bridge.QueuePacket(
self.channel, self.playermac, False, ack)
self.bridge.putInQueue(self.queue, qp)
elif packet.id in self.players:
print "player known:", packet.id
player = self.players[packet.id]
player.timeout = 10
if not player.active and isinstance(packet, packets.Button):
if self.askname:
nickrequest = packets.Nickrequest(packet.id)
qp = bridge.QueuePacket(self.channel,
self.playermac, False, nickrequest)
self.bridge.putInQueue(self.queue, qp)
else:
player.active = True
for callback in self.callbacks:
callback("added", player)
elif not player.active and isinstance(packet, packets.Nick):
if self.askname:
player.nick = packet.nick
player.active = True
for callback in self.callbacks:
callback("added", player)
else:
print "player unknown"
def sendAnnounce(self):
aq = bridge.QueuePacket(self.announcechannel,
self.announcemac, False, self.announce)
self.bridge.putInQueue(self.announcequeue, aq)
self.announcetimer = threading.Timer(1, self.sendAnnounce)
self.announcetimer.start()
def registerPlayerCallback(self, callback):
if not callback in self.callbacks:
self.callbacks.append(callback)

View File

@ -0,0 +1,207 @@
def inttouint32(v):
return chr(v&0xff)+chr((v>>8)&0xff)+chr((v>>16)&0xff)+chr((v>>24)&0xff)
def uint32toint(v):
return (ord(v[3])<< 24) + (ord(v[2])<<16) + (ord(v[1])<<8) + (ord(v[0]))
class Packet:
def __init__(self, command, id=None):
self.ctr = 0
if id == None:
message = command
command = message[2]
id = uint32toint(message[3:7])
self.ctr = uint32toint(message[7:11])
self.length = 32
self.protocol = 'G'
self.command = command
self.id = id
self.priority = 5
def toMessage(self):
message = chr(self.length)
message += self.protocol
message += self.command
message += inttouint32(self.id)
message += inttouint32(self.ctr)
return message
def headerString(self):
return "id=%d, ctr=%d"%(self.id, self.ctr)
def __str__(self):
s = "Packet with protocol=" + self.protocol
s += ", command=" + self.command
s += ", "+ self.headerString()
return s
class Button(Packet):
def __init__(self, id, button=None):
if button!= None:
Packet.__init__(self, 'B', id)
else:
message = id
Packet.__init__(self, message)
button = ord(message[11])
self.button = button
def toMessage(self):
base = Packet.toMessage(self)
return base + chr(self.button) + '\x00'*18
def __str__(self):
s = "Button packet with " + self.headerString()
s += ", button=%d"%self.button
return s
class Announce(Packet):
def __init__(self, gameMac, gameChannel, gameId, gameFlags, gameTitle):
#always a broadcast
Packet.__init__(self, 'A', 0)
self.gameMac = gameMac
self.gameChannel = gameChannel
self.gameId = gameId
self.gameFlags = gameFlags
self.gameTitle = gameTitle[0:8]
self.priority = 3
def toMessage(self):
message = Packet.toMessage(self)
message += ''.join([chr(x) for x in self.gameMac])
message += chr(self.gameChannel)
message += inttouint32(self.gameId)
message += chr(self.gameFlags)
message += self.gameTitle
if len(self.gameTitle) < 8:
message += '\x00'*(8-len(self.gameTitle))
return message
def __str__(self):
s = "Announce packet with " + self.headerString()
s += ", gameMac="+str(self.gameMac)
s += ", gameChannel=%d"%self.gameChannel
s += ", gameId=%d"%self.gameId
s += ", gameFlags=%d"%self.gameFlags
s += ", gameTitle="+self.gameTitle
return s
class Join(Packet):
def __init__(self, id, gameId=None):
if gameId != None:
Packet.__init__(self, 'J', id)
else:
message = id
Packet.__init__(self, message)
gameId = uint32toint(message[11:15])
self.gameId = gameId
def toMessage(self):
message = Packet.toMessage(self)
message += inttouint32(self.gameId)
message += '\x00'*15
return message
def __str__(self):
s = "Join packet with " + self.headerString()
s += ", gameId=%d"%self.gameId
return s
class Ack(Packet):
def __init__(self, id, ctr, flags=None):
if ctr != None and flags != None:
Packet.__init__(self, 'a', id)
self.ctr = ctr
else:
message = id
Packet.__init__(self, message)
flags = ord(message[11])
self.flags = flags
self.priority = 3
def toMessage(self):
message = Packet.toMessage(self)
message += chr(self.flags)
message += '\x00'*18
return message
def __str__(self):
s = "Ack packet with " + self.headerString()
s += ", flags=%d"%self.flags
return s
class Nickrequest(Packet):
def __init__(self, id):
Packet.__init__(self, 'N', id)
def __str__(self):
s = "Nickrequest packet with " + self.headerString()
return s
def toMessage(self):
message = Packet.toMessage(self)
message += '\x00'*19
return message
class Nick(Packet):
def __init__(self, id, flags=None, nick=None):
if flags != None and nick != None:
Packet.__init__(self, 'n', id)
else:
message = id
Packet.__init__(self, message)
flags = ord(message[11])
nick = message[12:30].rstrip(' \t\r\n\0')
self.flags = flags
self.nick = nick
def toMessage(self):
message = Packet.toMessage(self)
message += chr(self.flags)
message += self.nick
if len(self.nick) < 18:
message += '\x00'*(18-len(self.nick))
return message
def __str__(self):
s = "Nick packet with " + self.headerString()
s += ", flags=%d"%self.flags
s += ", nick="+self.nick
return s
class Text(Packet):
def __init__(self, id, x, y, flags, text):
Packet.__init__(self, 'T', id)
self.x = x
self.y = y
self. flags = flags
self.text = text[0:16]
def toMessage(self):
message = Packet.toMessage(self)
message += chr(self.x)
message += chr(self.y)
message += chr(self.flags)
message += self.text
if len(self.text) < 16:
message += '\x00'*(16-len(self.text))
return message
def __str__(self):
s = "Text packet with " + self.headerString()
s += ", x=%d"%self.x
s += ", y=%d"%self.y
s += ", flags=%d"%self.flags
s += ", text="+self.text
return s
def fromMessage(message):
if len(message) >= 30 and ord(message[0]) == 32 and message[1] == 'G':
if message[2] == 'B':
return Button(message)
if message[2] == 'n':
return Nick(message)
if message[2] == 'J':
return Join(message)
if message[2] == 'a':
return Ack(message)
return None

View File

@ -0,0 +1,92 @@
import serial
import string
import sys
import time
class SerialInterface:
def __init__ ( self, path2device, baudrate, timeout=0):
self.portopen = False
while not self.portopen:
try:
self.ser = serial.Serial(path2device, baudrate)
self.path2device = path2device
self.baudrate = baudrate
self.timeout = timeout+1
self.ser.flushInput()
self.ser.flushOutput()
if timeout:
self.ser.setTimeout(timeout+1)
self.portopen = True
except serial.SerialException:
print "exception while opening"
pass
time.sleep(1)
#print "done"
def close(self):
try:
self.portopen = False
self.ser.close()
except serial.SerialException:
pass
def reinit(self):
self.close()
print "reopening"
while not self.portopen:
self.__init__(self.path2device, self.baudrate, self.timeout)
time.sleep(1)
print "done"
def writeMessage(self,command,message):
enc = "\\"+ command + message.replace('\\','\\\\') + "\\0";
#print 'writing %s' % list(enc)
try:
self.ser.write(enc)
except :
pass
#self.reinit()
def readMessage(self):
data = ""
escaped = False
stop = False
start = False
inframe = False
command = ''
while True:
starttime = time.time()
c = self.ser.read(1)
endtime = time.time()
if len(c) == 0: #A timout occured
if endtime-starttime < self.timeout - 1:
print "port broken"
self.reinit()
raise Exception()
else:
#print 'TIMEOUT'
return (False, '')
if escaped:
if c == '\\':
d = '\\'
elif c == '0':
stop = True
inframe = False
else:
start = True
inframe = True
command = c
data = ""
escaped = False
elif c == '\\':
escaped = 1
else:
d = c
if start and inframe:
start = False
elif stop:
#print 'received message: len=%d data=%s'%(len(data),data)
#print 'received message. command=',command, "data=" ,list(data)
return (command, data)
elif escaped == False and inframe:
data += str(d)

5
tools/game/setup.py Normal file
View File

@ -0,0 +1,5 @@
from distutils.core import setup
setup(name='r0ketrem0te',
version='1.0',
packages=['r0ketrem0te'],
)

16
tools/game/testgame.py Normal file
View File

@ -0,0 +1,16 @@
import r0ketrem0te.game
import r0ketrem0te.bridge
import r0ketrem0te.packets
import time
import Queue
def receivedPacket(packet):
pass
game = r0ketrem0te.game.Game('/dev/ttyACM0', "testgame", 83,
81, [ord(x) for x in 'REM0T'], 2, True)
queue = Queue.Queue()
game.bridge.registerQueue(queue)
game.bridge.registerCallback(receivedPacket)
while True:
time.sleep(1)