Project

General

Profile

Revision 211

Added by Kevin Woo about 14 years ago

broken cardbox, needs to fix the statemachine

View differences:

trunk/cardbox/rs485_int.c
16 16
 * Copyright 2009 Kevin Woo <kwoo@2ndt.com>
17 17
 *
18 18
 ********/
19
/** @file uart.c
19
/** @file rs485_int.c
20 20
 *	
21 21
 *	@brief Implements UART functionality in hardware
22 22
 *
23 23
 *	@author Kevin Woo (kwoo)
24 24
 */
25 25

  
26
#include "uart.h"
26
#include "rs485_int.h"
27 27
#include <util/delay.h>
28 28
#include <stdint.h>
29 29

  
30 30
uint8_t received_byte;     //Byte received
31 31
uint8_t byte_ready;        //New byte has been received
32 32

  
33
void init_uart(uint16_t baud) {
33
void rs485_init(uint16_t baud) {
34 34
	// Set baud rate
35 35
	UBRRH = (uint8_t)(baud>>8);
36 36
	UBRRL = (uint8_t)baud;
......
44 44
    // Initialize receive variables
45 45
    byte_ready = 0;
46 46
    received_byte = 0x0;
47

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

  
49
int8_t uart_get_byte(uint8_t *output_byte) {
52
int8_t rs485_get_byte(uint8_t *output_byte) {
50 53
	if (byte_ready) {
51 54
		byte_ready = 0;
52 55
		*output_byte = received_byte;
......
56 59
	}
57 60
}
58 61

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

  
63 66
    // Enable writes and send
64
	uart_toggle_transmit(UART_TX_ON);
67
	rs485_toggle_transmit(UART_TX_ON);
65 68
    UDR = data;
66 69
	return;
67 70
}
68 71

  
69
void uart_toggle_transmit(uint8_t state) {
72
void rs485_toggle_transmit(uint8_t state) {
70 73
	if (state == UART_TX_ON) {
71 74
		PORTD |= TX_EN;
72 75
	} else {
......
81 84

  
82 85
ISR(USART_TX_vect) {
83 86
    // Re-enable reads
84
    uart_toggle_transmit(UART_TX_OFF);
87
    rs485_toggle_transmit(UART_TX_OFF);
85 88
}
trunk/cardbox/main.c
17 17
 *
18 18
 ********/
19 19
#include <util/delay.h>
20
#include "uart.h"
20
#include "rs485_int.h"
21 21
#include <avr/interrupt.h>
22 22
#include <avr/io.h>
23 23

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

  
27 27
/***** Keypad definitions ******/
......
48 48
#define LED_YELLOW (_BV(PC4))
49 49
#define LED_GREEN (_BV(PC3))
50 50

  
51
#define ADDR 2
51 52

  
52 53
/***** Global variables *****/
53 54

  
......
62 63
  return;	
63 64
}
64 65

  
66
/**
67
 * @brief Sets the LED to the specified state
68
 *
69
 * This sets LED which to the specified state. You can use this to set
70
 * multiple LEDs if you OR the LEDs desired into the which argument.
71
 *
72
 * @param which The LEDs to set
73
 * @parma state The state ON or OFF to set to the LEDs to
74
 * @return void
75
 */
76
void toggle_led(uint8_t which, uint8_t state) {
77
    if (state == ON) {
78
        LED_PORT &= ~(which);
79
    } else {
80
        LED_PORT |= (which);
81
    }
82
}
65 83

  
84

  
66 85
char get_button(void) {
67 86

  
68 87
	char ret = ' ';
......
134 153
  return ret;
135 154
}
136 155

  
137
int main(void)
138
{
156
typedef enum {
157
    req,
158
    press,
159
    send,
160
    rsp
161
} state_t;
139 162

  
140
  char c;
141
  serial_init(BAUD9600);
163

  
164
int main(void) {
165
    uint8_t mbuf[PROGD_PACKET_SIZE];
166
    uint8_t resp;
167
    uint8_t c;
168
    state_t state = req;
169

  
170
  rs485_init(BAUD9600); 
142 171
  init_pins();
143 172
  init_timer();
144 173
  sei();
145 174

  
146
  while(1)
147
  {
175
  while(1) {
148 176

  
149
    PORTC |= LED_RED | LED_GREEN | LED_YELLOW;
150
    
151
    //wait for key request from server
152
    while(serial_getchar()!=TT_GET_KEY);
177
      switch(state) {
178
          case req:
179
              toggle_led(LED_RED|LED_GREEN|LED_YELLOW, OFF);
180
              
181
              // Wait for a packet
182
              resp = parse_packet(mbuf, ADDR);
153 183

  
154
    PORTC &=~LED_YELLOW;
155
    reset_timer();
156
    reset_timeout_flag();
157
    start_timer();
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
                c = get_button();
158 195

  
159
    c = ' ';
160
    serial_disable_rx();
161
    while(c ==' ') {
162
        if (seconds > TIMEOUT_SECONDS) {
163
            set_timeout_flag();
164
            serial_putchar(TT_TIMEOUT);
165
            serial_enable_rx();
166
            break;
167
        }
196
                if (seconds > TIMEOUT_SECONDS) {
197
                    set_timeout_flag();
198
                    state = send;
199
                } else if (c != ' ') {
200
                    state = send;
201
                }
168 202

  
169
        c = get_button();
170
        _delay_ms(100);
171
    }
172
    serial_enable_rx();
203
                break;
204
        case send:
205
                if (timeoutflag == 1) {
206
                    send_packet(TT_TIMEOUT, ADDR);
207
                    state = req;
208
                } else {
209
                    send_packet_data(TT_SEND_KEY, ADDR, &c, 1);
210
                }
173 211

  
212
                state = rsp;
213
                break;
214
        case rsp:
215
                resp = parse_packet(mbuf, ADDR);
174 216

  
217
                if (resp == TT_ACK
218

  
219

  
220

  
221

  
222

  
175 223
    if (timeout_flag == 0) {
176 224
        //respond with key pressed
177
        serial_putchar(c);
225
        uart_send_byte(c);
178 226
        
179 227
        //wait for response
180 228
        c=0;
181 229
        reset_timeout_flag();
182 230
        reset_timer();
183
        while(!c && seconds < TIMEOUT_SECONDS)
184
          c = serial_getchar_nb();
231
        while((uart_get_byte(&c) < 0) && (seconds < TIMEOUT_SECONDS));
185 232

  
186 233
        PORTC |= LED_YELLOW;
187 234

  
trunk/cardbox/rs485_int.h
16 16
 * Copyright 2009 Kevin Woo <kwoo@2ndt.com>
17 17
 *
18 18
 ********/
19
/** @file uart.h
19
/** @file rs485_int.h
20 20
 *
21 21
 *	@brief Initializes UART functions using the UART hardware module
22 22
 *
......
53 53
 *         which msut be the value that is defined in the datasheet 
54 54
 *         for any particular speed (ie: 51 -> 9600bps)
55 55
 **/
56
void init_uart(uint16_t baud);
56
void rs485_init(uint16_t baud);
57 57
/** @brief Gets latest byte and returns it in output_byte. If the byte 
58 58
 *         was already read, returns -1 otherwise it returns 0 
59 59
 **/
60
int8_t uart_get_byte(uint8_t *output_byte);
60
int8_t rs485_get_byte(uint8_t *output_byte);
61 61
/** @brief Sends a character array of size size. If we are currently 
62 62
 *         transmitting it will block until the the current transmit 
63 63
 *         is done. 
64 64
 **/
65
void uart_send_byte(uint8_t data);
66
void uart_toggle_transmit(uint8_t state);
65
void rs485_send_byte(uint8_t data);
66
void rs485_toggle_transmit(uint8_t state);
67 67
#endif
trunk/cardbox/packet.c
1
#include <packet.h>
2

  
3

  
4
/**
5
 * @brief Packet handler states
6
 * @param sd Looking for a start delimiter
7
 * @param src Looking for a source
8
 * @param dest Looking for a destination
9
 * @param comd Looking for a command
10
 * @param read Reading data payload
11
 * @param cs Calcualting the checksum and returning
12
 */
13
typedef enum {
14
    sd,   
15
    src,  
16
    dest, 
17
    comd, 
18
    read, 
19
    cs    
20
} state_t;
21

  
22
/**
23
 * @brief Parses a tooltron packet
24
 * 
25
 * This is a state machine that parses the packet. It uses a software 
26
 * counter to track timeout status. The timeout is not reset unless
27
 * a fully valid packet is found. It will fail if there is a timeout,
28
 * crc error, or any error in the packet. All data will be placed in
29
 * mbuf. Note that mbuf must be able to handle PROGD_PACKET_SIZE
30
 * bytes.
31
 *
32
 * @pre mbuf is PROGD_PACKET_SIZE bytes large
33
 * @param mbuf Buffer to write the packet data payload to if there is one
34
 * @param addr The address of the sending node
35
 * @return the command received or TT_BAD on any error
36
 */
37
char parse_packet(uint8_t *mbuf, uint8_t addr) {
38
  uint8_t r;        // Byte from the network
39
  uint8_t crc;      // Running checksum of the packet
40
  uint8_t cmd;      // The command received
41
  uint8_t pos;      // Position in the message buffer
42
  uint8_t lim;      // Max number of bytes to read into the message buf
43
  state_t state;    // State machine
44
  uint16_t count;
45

  
46
  r = 0;
47
  crc = 0;
48
  cmd = 0;
49
  pos = 0;
50
  lim = 0;
51
  state = sd;
52
  count = 0;
53

  
54
  while (1) {
55
    // Wait for the next byte
56
    while ((rs485_get_byte(&r)) < 0) {
57
        if (count >= MAX_TIMEOUT) {
58
            return TT_BAD;
59
        } else {
60
            count++;
61
        }
62
    }
63

  
64
    switch (state) {
65
        case sd:
66
            if (r == DELIM) {
67
                state = src;
68
            }
69
            break;
70

  
71
        case src:
72
            if (r == DELIM) {
73
                state = src;
74
            } else {
75
                crc = r;
76
                state = dest;
77
            }
78
            break;
79

  
80
        case dest:
81
            if (r == DELIM) {
82
                state = src;
83
            } else if (r == addr) {
84
                crc ^= r;
85
                state = comd;
86
            } else {
87
                state = sd;
88
            }
89
            break;
90

  
91
        case comd:
92
            cmd = r;
93
            crc ^= r;
94

  
95
            if (r == DELIM) {
96
                state = src;
97
            } else if (r == TT_PROGM) {
98
                lim = PROGM_PACKET_SIZE;
99
                state = read;
100
            } else if (r == TT_PROGD) {
101
                lim = PROGD_PACKET_SIZE;
102
                state = read;
103
            } else if (r == TT_SEND_KEY) {
104
                lim = SEND_KEY_PACKET_SIZE;
105
                state = read;
106
            } else {
107
                state = cs;
108
            }
109
            break;
110

  
111
        case read:
112
            mbuf[pos] = r;
113
            crc ^= r;
114
            pos++;
115

  
116
            if (pos == lim) {
117
                state = cs;
118
            }
119

  
120
            break;
121
       
122
        case cs:
123
            if (r == crc) {
124
                if (cmd == TT_RESET) {
125
                    reset();
126
                }
127
                return cmd;
128
            } else {
129
                return TT_BAD;
130
            }
131

  
132
            break;
133

  
134
        default:
135
            return TT_BAD;
136
    }
137
  }
138
}
139

  
140
/**
141
 * @brief Sends a packet of type cmd onto the network
142
 * @param cmd The command to send
143
 * @param addr The address of the sending node
144
 */
145
void send_packet(uint8_t cmd, uint8_t addr) {
146
    rs485_send_byte(DELIM);
147
    rs485_send_byte(addr);
148
    rs485_send_byte(SERVER);
149
    rs485_send_byte(cmd);
150
    rs485_send_byte(addr ^ SERVER ^ cmd);
151
}
152

  
153
/**
154
 * @brief Sends a packet of type cmd onto the network
155
 * @param cmd The command to send
156
 * @param addr The address of the sending node
157
 * @param data Pointer to data
158
 * @param len Number of bytes to send
159
 */
160
void send_packet_data(uint8_t cmd, uint8_t addr, uint8_t* data, uint8_t len) {
161
    uint8_t i;
162
    uint8_t crc = 0;
163

  
164
    rs485_send_byte(DELIM);
165
    rs485_send_byte(addr);
166
    rs485_send_byte(SERVER);
167
    rs485_send_byte(cmd);
168
    for (i = 0; i < len; i++) {
169
        crc  ^= data[i];
170
        rs485_send_byte(data[i]);
171
    }
172
    rs485_send_byte(addr ^ SERVER ^ cmd ^ crc);
173
}
174

  
trunk/cardbox/Makefile
91 91
#     Each directory must be seperated by a space.
92 92
#     Use forward slashes for directory separators.
93 93
#     For a directory that has spaces, enclose it in quotes.
94
EXTRAINCDIRS = Y:/code/firefly_plus_lib
95
#C:\WinAVR\include\fwr
94
EXTRAINCDIRS = ../common
96 95

  
97 96

  
98 97
# Compiler flag to set the C Standard level.
trunk/cardbox/packet.h
1
#ifndef _PACKET_H_
2
#define _PACKET_H_
3

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

  
9
/** @brief Max time to wait until we exit the packet handler */
10
#define MAX_TIMEOUT 60000
11

  
12
char parse_packet(uint8_t *mbuf, uint8_t addr);
13
void send_packet(uint8_t cmd, uint8_t addr);
14
void send_packet_data(uint8_t cmd, uint8_t addr, uint8_t* data, uint8_t len);
15

  
16

  
17
#endif

Also available in: Unified diff