BlinkenArea - GitList
Repositories
Blog
Wiki
flaneth
Code
Commits
Branches
Tags
Search
Tree:
e8658d5
Branches
Tags
master
flaneth
firmware.dartboard
dart.c
initial commit after making CF identify work
Stefan Schuermans
commited
e8658d5
at 2012-04-15 19:57:57
dart.c
Blame
History
Raw
/* flaneth - flash and ethernet - dartboard mod * version 0.1 date 2008-11-09 * Copyright (C) 2007-2008 Stefan Schuermans <stefan@schuermans.info> * Copyleft: GNU public license V2 - http://www.gnu.org/copyleft/gpl.html * a BlinkenArea project - http://www.blinkenarea.org/ */ #include <avr/io.h> #include <avr/interrupt.h> #include "dart.h" #include "debug.h" #include "macros.h" #include "nethelp.h" #include "udp.h" // dartboard connection // - 7 row pins connected via shottky diode (low passes to dartboard) // - 12 column pins connected directly // IO-Pins // PB0: col10 // PB2: col9 // PB3: col8 // PC[0-7]: col[0-7] // PF[0-6]: row[0-6] // PF7: col11 // constants #define DartRows (7) #define DartCols (12) #define DartFields (DartRows * DartCols) #define DartDisableTicks (5) #define DartQueueSize (16) // if waiting for a field to be hit volatile unsigned char DartActive = 1; // current row being read volatile unsigned char DartRow = DartRows; volatile unsigned char DartRowBits = 1 << DartRows; // always 1 << DartRow // field that has been hit volatile unsigned char DartField = DartFields; // ticks dartboard is disabled // - used after field has been hit to disable board for some time unsigned char DartDisable = 0; // destination to send dart UDP packets to unsigned char DartIp[4]; unsigned short DartPort = 0; // dart queue unsigned char DartQueueStart = 0; unsigned char DartQueueEnd = 0; unsigned char DartQueue[DartQueueSize]; // 128us interrupt (timer 2 overflow) SIGNAL( SIG_OVERFLOW2 ) { unsigned char b, c, f, col; // do nothing if not waiting for a field to be hit if( ! DartActive ) return; // read inputs b = ~PINB & 0x0D; c = ~PINC; f = ~PINF & 0x80; // check if any input is active // - make common case (no input active) fast if( b | c | f ) { // no column col = DartCols; // find active column (any active column if multiple active) if( b ) { if( b & 0x08 ) col = 8; else if( b & 0x04 ) col = 9; else if( b & 0x01 ) col = 10; } else if( c ) { if( c & 0x0F ) { if( c & 0x01 ) col = 0; else if( c & 0x02 ) col = 1; else if( c & 0x04 ) col = 2; else if( c & 0x08 ) col = 3; } else if( c & 0xF0 ) { if( c & 0x10 ) col = 4; else if( c & 0x20 ) col = 5; else if( c & 0x40 ) col = 6; else if( c & 0x80 ) col = 7; } } else if( f ) { if( f & 0x80 ) col = 11; } // active column found if( col < DartCols ) { // save field number DartField = DartRow * DartCols + col; // do not wait for a field to be hit any more DartActive = 0; } } // if( b | c | f ) // next row DartRow++; DartRowBits <<= 1; if( DartRow >= DartRows ) { DartRow = 0; DartRowBits = 0x01; } // select new row PORTF = 0xFF & ~DartRowBits; } // initialize void DartInit( void ) // (extern) { // col to input with pull-up // row to output, high PORTB |= 0x0D; DDRB &= ~0x0D; PORTC = 0xFF; DDRC = 0x00; PORTF = 0xFF; DDRF = 0x7F; // configure timer 2 to 128us interval TCCR2 = 0<<FOC2 | 0<<WGM21 | 0<<WGM20 | // normal mode 0<<COM21 | 0<<COM20 | // no waveform generation 0<<CS22 | 1<<CS21 | 0<<CS20; // 1/8 of sysclock (16MHz) -> overflow every 128us // enable timer 2 overflow interrupt TIMSK |= 1<<TOIE2; } // convert field number to meaning void DartField2Meaning( unsigned char field, unsigned char * factor, unsigned char * value ) { switch( field ) { case 0: *factor = 3; *value = 13; break; case 1: *factor = 1; *value = 18; break; case 2: *factor = 1; *value = 10; break; case 3: *factor = 1; *value = 15; break; case 4: *factor = 2; *value = 15; break; case 5: *factor = 3; *value = 5; break; case 6: *factor = 2; *value = 2; break; case 7: *factor = 1; *value = 2; break; case 8: *factor = 1; *value = 17; break; case 9: *factor = 1; *value = 3; break; case 10: *factor = 1; *value = 8; break; case 11: *factor = 3; *value = 7; break; case 12: *factor = 1; *value = 4; break; case 13: *factor = 3; *value = 6; break; case 14: *factor = 3; *value = 10; break; case 15: *factor = 3; *value = 15; break; case 16: *factor = 0; *value = 0; break; case 17: *factor = 1; *value = 5; break; case 18: *factor = 0; *value = 0; break; case 19: *factor = 1; *value = 2; break; case 20: *factor = 1; *value = 17; break; case 21: *factor = 1; *value = 3; break; case 22: *factor = 1; *value = 19; break; case 23: *factor = 1; *value = 7; break; case 24: *factor = 1; *value = 13; break; case 25: *factor = 1; *value = 6; break; case 26: *factor = 1; *value = 10; break; case 27: *factor = 1; *value = 15; break; case 28: *factor = 2; *value = 25; break; case 29: *factor = 1; *value = 12; break; case 30: *factor = 1; *value = 25; break; case 31: *factor = 3; *value = 2; break; case 32: *factor = 3; *value = 17; break; case 33: *factor = 3; *value = 3; break; case 34: *factor = 3; *value = 19; break; case 35: *factor = 1; *value = 16; break; case 36: *factor = 3; *value = 4; break; case 37: *factor = 1; *value = 6; break; case 38: *factor = 1; *value = 1; break; case 39: *factor = 1; *value = 20; break; case 40: *factor = 2; *value = 10; break; case 41: *factor = 3; *value = 12; break; case 42: *factor = 2; *value = 17; break; case 43: *factor = 1; *value = 9; break; case 44: *factor = 1; *value = 14; break; case 45: *factor = 1; *value = 11; break; case 46: *factor = 1; *value = 19; break; case 47: *factor = 3; *value = 16; break; case 48: *factor = 1; *value = 13; break; case 49: *factor = 3; *value = 18; break; case 50: *factor = 3; *value = 1; break; case 51: *factor = 3; *value = 20; break; case 52: *factor = 2; *value = 6; break; case 53: *factor = 1; *value = 5; break; case 54: *factor = 2; *value = 3; break; case 55: *factor = 3; *value = 9; break; case 56: *factor = 3; *value = 14; break; case 57: *factor = 3; *value = 11; break; case 58: *factor = 3; *value = 8; break; case 59: *factor = 1; *value = 7; break; case 60: *factor = 1; *value = 4; break; case 61: *factor = 1; *value = 18; break; case 62: *factor = 1; *value = 1; break; case 63: *factor = 1; *value = 20; break; case 64: *factor = 2; *value = 13; break; case 65: *factor = 1; *value = 12; break; case 66: *factor = 2; *value = 19; break; case 67: *factor = 1; *value = 9; break; case 68: *factor = 1; *value = 14; break; case 69: *factor = 1; *value = 11; break; case 70: *factor = 1; *value = 8; break; case 71: *factor = 1; *value = 16; break; case 72: *factor = 2; *value = 4; break; case 73: *factor = 2; *value = 18; break; case 74: *factor = 2; *value = 1; break; case 75: *factor = 2; *value = 20; break; case 76: *factor = 2; *value = 5; break; case 77: *factor = 2; *value = 12; break; case 78: *factor = 2; *value = 7; break; case 79: *factor = 2; *value = 9; break; case 80: *factor = 2; *value = 14; break; case 81: *factor = 2; *value = 11; break; case 82: *factor = 2; *value = 8; break; case 83: *factor = 2; *value = 16; break; default: *factor = 0; *value = 0; break; } } // task procedure void DartTask( void ) // (extern) { unsigned char factor, value, len, idx; struct { struct UdpPacket udp; char text[6]; } data; // a field has been hit if( DartField < DartFields ) { // convert field number to meaning DartField2Meaning( DartField, &factor, &value ); if( factor <= 0 || value <= 0 ) { debug_dart_printf( "field %u hit", DartField ); } else { debug_dart_printf( "%ux%u (field %u) hit", factor, value, DartField ); // put into queue idx = DartQueueEnd + 1; if( idx >= DartQueueSize ) idx = 0; if( idx != DartQueueStart ) { DartQueue[DartQueueEnd] = DartField; DartQueueEnd = idx; } // UDP packets have been requested if( DartPort != 0 ) { len = 0; data.text[len++] = factor + '0'; data.text[len++] = 'x'; if( value >= 10 ) data.text[len++] = value / 10 + '0'; data.text[len++] = value % 10 + '0'; data.text[len++] = '\r'; data.text[len++] = '\n'; // send UDP packet data.udp.UdpHdr.SrcPort = htons( 501 ); data.udp.UdpHdr.DestPort = htons( DartPort ); ip_cpy( data.udp.IpHdr.Dest, DartIp ); UdpSend( (unsigned char *)&data, sizeof( data ) - sizeof( data.text) + len ); } } // reset field DartField = DartFields; // disable dart board for a short time DartDisable = DartDisableTicks; } } // tick procedure - call every 200ms void DartTick200( void ) // (extern) { // dart board is disabled if( DartDisable > 0 ) { // count down ticks DartDisable--; // disable period elapsed if( DartDisable <= 0 ) { // switch dart board to active DartActive = 1; } } } // a dart request packet has been received void DartRequest( unsigned char ip[4], unsigned short port ) // (extern) { // save new destination ip_cpy( DartIp, ip ); DartPort = port; } // poll for dart event void DartPoll( unsigned char * factor, unsigned char * value ) // (extern) { unsigned char field, fac, val; // dart queue empty if( DartQueueStart == DartQueueEnd ) { *factor = 0; *value = 0; return; } // get entry from queue field = DartQueue[DartQueueStart]; DartQueueStart++; if( DartQueueStart >= DartQueueSize ) DartQueueStart = 0; // convert field number to meaning DartField2Meaning( field, &fac, &val ); if( factor <= 0 || value <= 0 ) { debug_dart_printf( "from queue: field %u", field ); } else { debug_dart_printf( "from queue: %ux%u (field %u)", fac, val, field ); } *factor = fac; *value = val; }