Project

General

Profile

Statistics
| Revision:

root / trunk / cardbox / packet.c @ 211

History | View | Annotate | Download (4.12 KB)

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