Project

General

Profile

Statistics
| Revision:

root / trunk / cardbox / packet.c @ 213

History | View | Annotate | Download (4.02 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
              return cmd;
125
            } else {
126
                return TT_BAD;
127
            }
128

    
129
            break;
130

    
131
        default:
132
            return TT_BAD;
133
    }
134
  }
135
}
136

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

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

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