Project

General

Profile

Revision 213

fixed cardbox code for new board, updated tooltron.py for new cardbox

View differences:

trunk/cardbox/tooltron.h
1
/********
2
 * This file is part of Tooltron.
3
 *
4
 * Tooltron is free software: you can redistribute it and/or modify
5
 * it under the terms of the Lesser GNU General Public License as published by
6
 * the Free Software Foundation, either version 3 of the License, or
7
 * (at your option) any later version.
8
 *
9
 * Tooltron is distributed in the hope that it will be useful,
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
 * Lesser GNU General Public License for more details.
13
 * You should have received a copy of the Lesser GNU General Public License
14
 * along with Tooltron.  If not, see <http://www.gnu.org/licenses/>.
15
 *
16
 * Copyright 2009 Kevin Woo <kwoo@2ndt.com>
17
 *
18
 ********/
19
#ifndef _TOOLTRON_H_
20
#define _TOOLTRON_H_
21

  
22
#define TT_GET_KEY 'k'
23
#define TT_ACK     'a'
24
#define TT_NACK    'n'
25
#define TT_TO      'f'
26
#define TT_TIMEOUT 't'
27

  
28
#define TIMEOUT_SECONDS 10 
29

  
30
#endif
trunk/cardbox/rs485_int.c
32 32

  
33 33
void rs485_init(uint16_t baud) {
34 34
	// Set baud rate
35
	UBRRH = (uint8_t)(baud>>8);
36
	UBRRL = (uint8_t)baud;
35
	UBRR0H = (uint8_t)(baud>>8);
36
	UBRR0L = (uint8_t)baud;
37 37
	
38 38
	// Enable RX/TX and RX/TX Interrupt
39
	UCSRB = _BV(RXCIE) | _BV(RXEN) | _BV(TXCIE) | _BV(TXEN);
39
	UCSR0B = _BV(RXCIE0) | _BV(RXEN0) | _BV(TXCIE0) | _BV(TXEN0);
40 40
 
41 41
	// Enable the TXEN pin as output
42 42
	DDRD |= TX_EN;
......
46 46
    received_byte = 0x0;
47 47

  
48 48
    // Set to receive mode
49
    rs485_toggle_transmit(TX_OFF);
49
    rs485_toggle_transmit(RS485_TX_OFF);
50 50
}
51 51

  
52 52
int8_t rs485_get_byte(uint8_t *output_byte) {
......
61 61

  
62 62
void rs485_send_byte(uint8_t data) {
63 63
	//Waits until current transmit is done
64
    while (!(UCSRA & _BV(UDRE)));
64
    while (!(UCSR0A & _BV(UDRE0)));
65 65

  
66 66
    // Enable writes and send
67
	rs485_toggle_transmit(UART_TX_ON);
68
    UDR = data;
67
	rs485_toggle_transmit(RS485_TX_ON);
68
	UDR0 = data;
69 69
	return;
70 70
}
71 71

  
72 72
void rs485_toggle_transmit(uint8_t state) {
73
	if (state == UART_TX_ON) {
73
	if (state == RS485_TX_ON) {
74 74
		PORTD |= TX_EN;
75 75
	} else {
76 76
		PORTD &= ~TX_EN;
......
78 78
}
79 79

  
80 80
ISR(USART_RX_vect) {
81
    received_byte = UDR;
81
    received_byte = UDR0;
82 82
    byte_ready = 1;    
83 83
}
84 84

  
85 85
ISR(USART_TX_vect) {
86 86
    // Re-enable reads
87
    rs485_toggle_transmit(UART_TX_OFF);
87
    rs485_toggle_transmit(RS485_TX_OFF);
88 88
}
trunk/cardbox/timer.c
28 28
#include <avr/io.h>
29 29
#include <avr/interrupt.h>
30 30

  
31
char timeout_flag=0;
31 32

  
33
char get_timeout_flag(void){
34
  return timeout_flag;
35
}
36

  
32 37
//Initializes all the timer1 registers
33 38
void init_timer() {
34 39
	//Clears the control registers for timer 1
trunk/cardbox/main.c
23 23

  
24 24
#include <tooltron.h>
25 25
#include "timer.h"
26
#include "packet.h"
26 27

  
27 28
/***** Keypad definitions ******/
28 29
/** @brief ROW1 of the keypad */
......
47 48
#define LED_RED (_BV(PC5))
48 49
#define LED_YELLOW (_BV(PC4))
49 50
#define LED_GREEN (_BV(PC3))
51
#define LED_PORT PORTC
50 52

  
51 53
#define ADDR 2
52 54

  
......
58 60

  
59 61
  DDRC |= LED_RED | LED_YELLOW | LED_GREEN;
60 62

  
61
  PORTC |= LED_RED | LED_GREEN | LED_YELLOW;
63
  LED_PORT |= LED_RED | LED_GREEN | LED_YELLOW;
62 64
  
63 65
  return;	
64 66
}
......
167 169
    uint8_t c;
168 170
    state_t state = req;
169 171

  
170
  rs485_init(BAUD9600); 
171
  init_pins();
172
  init_timer();
173
  sei();
172
    rs485_init(BAUD9600); 
173
    init_pins();
174
    init_timer();
175
    sei();
174 176

  
175
  while(1) {
177
    while(1) {
176 178

  
177
      switch(state) {
178
          case req:
179
              toggle_led(LED_RED|LED_GREEN|LED_YELLOW, OFF);
179
	while(1) {
180
	    toggle_led(LED_GREEN, ON);
181
	    send_packet(TT_TIMEOUT, ADDR);
182
	    _delay_ms(100);
183
	    toggle_led(LED_GREEN, OFF);
184
	    _delay_ms(100);
185
	}
186

  
187
	switch(state) {
188
	    case req:
189
		toggle_led(LED_RED|LED_GREEN|LED_YELLOW, OFF);
180 190
              
181
              // Wait for a packet
182
              resp = parse_packet(mbuf, ADDR);
191
		// Wait for a packet
192
		resp = parse_packet(mbuf, ADDR);
183 193

  
184
              if (resp == TT_GET_KEY) {
185
                  toggle_led(LED_YELLOW, ON);
186
                  reset_timer();
187
                  reset_timeout_flag();
188
                  start_timer();
189
                  c = ' ';
190
                  state = press;
191
              }
192
              break;
193
            case press:
194
		if (resp == TT_GET_KEY) {
195
		    toggle_led(LED_YELLOW, ON);
196
		    reset_timer();
197
		    reset_timeout_flag();
198
		    start_timer();
199
		    c = ' ';
200
		    state = press;
201
		}
202
		else if(resp != TT_BAD){
203
		    toggle_led(LED_RED, ON);
204
		    while(1);
205
		}
206
		break;
207
	    case press:
194 208
                c = get_button();
195

  
209
		
196 210
                if (seconds > TIMEOUT_SECONDS) {
197 211
                    set_timeout_flag();
198 212
                    state = send;
......
201 215
                }
202 216

  
203 217
                break;
204
        case send:
205
                if (timeoutflag == 1) {
218
            case send:
219
                if (get_timeout_flag() == 1) {
206 220
                    send_packet(TT_TIMEOUT, ADDR);
207 221
                    state = req;
208 222
                } else {
......
211 225

  
212 226
                state = rsp;
213 227
                break;
214
        case rsp:
215
                resp = parse_packet(mbuf, ADDR);
228
            case rsp:
229
		resp = parse_packet(mbuf, ADDR);
216 230

  
217
                if (resp == TT_ACK
231
                if (resp == TT_ACK) {
232
		    toggle_led(LED_GREEN, ON);
233
		}
234
		else {
235
		    toggle_led(LED_RED, ON);
236
		}
237
		_delay_ms(1000);
238
		toggle_led(LED_RED, OFF);
239
		toggle_led(LED_GREEN, ON);
240
		state = req;
241
		break;
242
	}
218 243

  
244
    } 
219 245

  
220

  
221

  
222

  
223
    if (timeout_flag == 0) {
224
        //respond with key pressed
225
        uart_send_byte(c);
226
        
227
        //wait for response
228
        c=0;
229
        reset_timeout_flag();
230
        reset_timer();
231
        while((uart_get_byte(&c) < 0) && (seconds < TIMEOUT_SECONDS));
232

  
233
        PORTC |= LED_YELLOW;
234

  
235
        switch(c)
236
        {
237
          case TT_ACK:
238
            PORTC &= ~LED_GREEN;
239
            break;
240
          
241
          case TT_NACK:
242
            PORTC &= ~LED_RED;
243
            break;
244
          
245
	  case TT_GET_KEY: //this means the states are messed up
246
            PORTC &= (~LED_RED & ~LED_YELLOW & ~LED_GREEN);
247
            break;
248

  
249
	  case 0: //timeout
250
	    PORTC &= (~LED_RED & ~LED_YELLOW);
251
	    break;	    
252

  
253
	default: //bad packet
254
            PORTC &= (~LED_RED & ~LED_GREEN);
255
            break;
256
        }
257
        
258
        stop_timer();
259
        _delay_ms(1000);
260
            
261
      }
262
    } 
263
  return 0;
264
    
246
    return 0;    
265 247
}
trunk/cardbox/rs485_int.h
30 30
#include <avr/interrupt.h>
31 31
#include <stdint.h>
32 32
/** **/
33
#define UART_TX_OFF 0
34
#define UART_TX_ON 1
33
#define RS485_TX_OFF 0
34
#define RS485_TX_ON 1
35 35

  
36 36
/** @brief RX Pin for the UART **/
37 37
#define RX		_BV(PORTD0)
38 38
#define TX		_BV(PORTD1)
39
#define TX_EN	_BV(PORTD5)
39
#define TX_EN	_BV(PORTD2)
40 40

  
41 41
/**
42 42
 * @brief This si the value to pass into UBRR tos et the baudrate.
trunk/cardbox/timer.h
32 32
/** Globals **/
33 33
volatile char seconds;		//Seconds elapsed
34 34
volatile char minutes;		//Minutes exlapsed
35
char timeout_flag; //Indicates that timeout has occured
36 35

  
37 36
/** @brief Seconds that have elapsed since the timer started */
38 37
//extern volatile char seconds;
......
52 51
void reset_timeout_flag(void);
53 52
/** @brief Sets the timeout flag to 1 */
54 53
void set_timeout_flag(void);
54
/** @brief Gets the timeout flag (nonzero means set) */
55
char get_timeout_flag(void);
55 56

  
56 57
#endif
trunk/cardbox/packet.c
121 121
       
122 122
        case cs:
123 123
            if (r == crc) {
124
                if (cmd == TT_RESET) {
125
                    reset();
126
                }
127
                return cmd;
124
	      return cmd;
128 125
            } else {
129 126
                return TT_BAD;
130 127
            }
trunk/cardbox/packet.h
3 3

  
4 4
#include <tooltron.h>
5 5
#include <avr/eeprom.h>
6
#include "rs485_poll.h"
7
#include "bootloader.h"
6
#include "rs485_int.h"
8 7

  
9 8
/** @brief Max time to wait until we exit the packet handler */
10 9
#define MAX_TIMEOUT 60000
trunk/swipe/tooltron.py
44 44
import getpass
45 45
from time import *
46 46

  
47
keypad = []
48 47
keypadTimeout = 11 #in seconds
49 48

  
50 49
#this table maps which keypad button to press for each tool. This
......
189 188
    return
190 189

  
191 190

  
192
if len(sys.argv) < 3:
193
    print "usage: tooltron.py /path/to/keypad/device /path/to/tool/bus/device"
191
if len(sys.argv) < 2:
192
    print "usage: tooltron.py /path/to/bus/device"
194 193

  
195 194
else:
196 195

  
......
206 205

  
207 206
    qry = "SELECT tools_6 FROM civicrm_value_roboclub_info_2 WHERE card_number_1 = "
208 207

  
209
    # user has 10 seconds to press a key, after that the keypad device
210
    # should send a timeout packet. This is a non-blocking serial
211
    # device so we can re-transmit the key request when the user
212
    # swipes a card instead of being stuck on a blocking read call
213
    keypad = serial.Serial(sys.argv[1], BAUD_RATE, timeout = 0) 
214
    keypad.flushInput()
215
    print keypad
216

  
217
    bus = serial.Serial(sys.argv[2], BAUD_RATE, timeout = 2)
208
    bus = serial.Serial(sys.argv[1], BAUD_RATE, timeout = 2)
218 209
    bus.flushInput()
219 210
    print bus
220 211
    
......
226 217
        bus.write(msg)
227 218
        return
228 219

  
220
    def sendKeyRequest():
221
       tn = 2 #2 is the ID for the cardbox
222
       msg = '^' + chr(1) + chr(tn) + TT_GET_KEY + chr(1 ^ tn ^ ord(TT_GET_KEY))
223
       print "seding key request"
224
       bus.write(msg)
225
       return
226

  
227
    def sendAck(toolNum):
228
       msg = '^' + chr(1) + chr(toolNum) + TT_ACK + chr(1 ^ tn ^ ord(TT_ACK))
229
       print "seding ACK to",toolNum
230
       bus.write(msg)
231
       return
232

  
233
    def sendNack(toolNum):
234
       msg = '^' + chr(1) + chr(toolNum) + TT_NACK + chr(1 ^ tn ^ ord(TT_NACK))
235
       print "seding ACK to",toolNum
236
       bus.write(msg)
237
       return
238

  
239

  
240
    #returns key if the key_send packet is recived from tool ID 2
241
    # otherwise returns 0
242
    def readKey():
243
       startDelim = bus.read(1)
244
       if startDelim == '^':
245
          src = bus.read(1)
246
          if src == 0:
247
             return 0
248
          dest = bus.read(1)
249
          if dest == 0:
250
             return 0
251
          packetType = bus.read(1)
252
          if packetType == 0:
253
             return 0
254
          key = bus.read(1)
255
          if key == 0:
256
             return 0
257
          crc = bus.read(1)
258

  
259
          print "got packet"
260
          if src != 2 or dest != 1 or packetType != TT_KEY_SEND:
261
             print "Bad packet! ^",src,dest,packetType,key,crc
262

  
263
          if chr(ord(src) ^ ord(dest) ^ ord(packetType) ^ ord(key)) == crc:
264
             return key
265
          else:
266
             print "xor fail. got", crc, "should have been got",(chr(ord(src) ^ ord(dest) ^ ord(packetType) ^ ord(key)))
267

  
268
          return 0
269

  
270
       else:
271
          print "did not get start delim!: ", ord(startDelim)
272
          return 0
273
       
229 274
    #returns [src, data] or [] on error
230 275
    def readTool():
231 276
        ret = [0,0,0]
......
263 308
        if id != None:
264 309
            print "\n-----------\nid# ", id.group(1)
265 310

  
311
            sendKeyRequest()
312
            startTime = time.time()
266 313

  
267
            print "sending key request"
268
            keypad.flushInput()
269
            keypad.write(TT_GET_KEY)
270

  
271 314
            cursor.execute(qry + id.group(1))
272 315

  
273 316
            result = cursor.fetchall()
......
318 361

  
319 362
            print user
320 363

  
321
            startTime = time.time();
322
            resp = ""
323
            while resp=="":
324
               resp = keypad.read(1)
364

  
365
            resp = 0
366
            while resp==0:
367
               resp = readKey()
368

  
325 369
               #no lock since we are just reading and we can afford to
326 370
               #miss a loop
327 371
               if idready == True:
......
334 378
                  logMessage("keypad timed out")
335 379
                  break
336 380

  
337
            #if we have a vaid response
381
            #if we have a valid response
338 382
            #sometimes the FTDI chip seems to give a zero as a string when power is reset
339 383
            if resp != "" and ord(resp) != 0 and resp != TT_TIMEOUT:
340 384

  
......
343 387
               print "request:",resp,"(",ord(resp),") ",toolNameLong
344 388

  
345 389
               if acl.count(resp) > 0:
346
                  keypad.write(TT_ACK)
390
                  sendAck(2)
347 391
                  sendTool(resp)
348 392
                  print "ACCESS GRANTED"
349 393
                  logMessage(user+" ACCESSED tool "+toolNameLong)
......
361 405
                                   str(MAX_TOOL_FAILS)+" times in a row.")
362 406

  
363 407
               else:
364
                  keypad.write(TT_NACK)
408
                  sendNack(2)
365 409
                  print "ACCESS DENIED!!"
366 410
                  logMessage(user + " DENIED on tool "+toolNameLong)
367 411

  
368 412
               clear_id()
369 413

  
370 414
        elif resp == 0 or ord(resp) == 0: #if we get noise, send timeout to reset and sync states
371
           keypad.write(TT_TIMEOUT);
415
           keypad.write(TT_TIMEOUT)
372 416
           print "ERROR: got strange byte, timing out"
373 417
           logMessage("ERROR: got 0 as a byte, sending timeout (cardbox power issue?)")
374 418
        else:
trunk/common/tooltron.h
28 28

  
29 29
// These are the bytes used in the messaage types
30 30
#define TT_GET_KEY  'k'     // Get a key from the keyboard
31
#define TT_SEND_KEY 's'     // Send a Key back (has 1 extra data packet)
31 32
#define TT_ACK      'a'     // Ack
32 33
#define TT_NACK     'n'     // Nack
33 34
#define TT_ON       'o'     // Turn the tool on
......
42 43
// Number of bytes that the PROGx packets have in the payload
43 44
#define PROGM_PACKET_SIZE 2
44 45
#define PROGD_PACKET_SIZE 32
46
#define SEND_KEY_PACKET_SIZE 1
45 47

  
46 48
// Tool timeout?
47 49
#define TIMEOUT_SECONDS 10 
trunk/programmer/test/main.c
32 32

  
33 33
#define RELAY       _BV(PORTD4)
34 34
#define VAC_SENSE   _BV(PIND3)
35
#define BUT_RED     _BV(PINB4)
36
#define BUT_BLACK   _BV(PINB3)
35
#define BUT_RED     _BV(PINB4)#define BUT_BLACK   _BV(PINB3)
37 36
#define LED_GREEN   _BV(PORTB2)
38 37
#define LED_YELLOW  _BV(PORTB1)
39 38
#define LED_RED     _BV(PORTB0)
......
108 107

  
109 108
    uint8_t r;
110 109

  
111
    //eeprom_write_byte(1, 18);
110
    //eeprom_write_byte(1, 12);
112 111

  
113 112
    PORTB = 0x7;
114 113

  
115
    /* myaddr = eeprom_read_byte(1); */
116
    /* if (myaddr == 18) { */
117
    /*    PORTB = 0x7; */
118
    /* } */
119
    /* _delay_ms(1000); */
120
    /* PORTB |= _BV(PORTB0); */
121
    /* _delay_ms(1000); */
122
    /* reset(); */
114
    myaddr = eeprom_read_byte(1);
115
    if (myaddr == 11) {
116
       PORTB = 0;
117
       while(1);
118
    }
119
    _delay_ms(1000);
120
    PORTB |= _BV(PORTB0);
121
    _delay_ms(1000);
122
    reset();
123 123

  
124 124
    while(1) {
125
        _delay_ms(1000);
125
    	_delay_ms(1000);
126 126
        PORTB |= _BV(PORTB0);
127 127
        _delay_ms(1000);
128 128
        PORTB &= ~_BV(PORTB0);

Also available in: Unified diff