Project

General

Profile

Statistics
| Revision:

root / trunk / cardbox / packet.c @ 213

History | View | Annotate | Download (4.02 KB)

1 189 kwoo
#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 199 kwoo
 * @param addr The address of the sending node
35 189 kwoo
 * @return the command received or TT_BAD on any error
36
 */
37 199 kwoo
char parse_packet(uint8_t *mbuf, uint8_t addr) {
38 189 kwoo
  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 199 kwoo
            } else if (r == addr) {
84 189 kwoo
                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 211 kwoo
            } else if (r == TT_SEND_KEY) {
104
                lim = SEND_KEY_PACKET_SIZE;
105
                state = read;
106 189 kwoo
            } 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 213 bneuman
              return cmd;
125 189 kwoo
            } 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 199 kwoo
 * @param addr The address of the sending node
141 189 kwoo
 */
142 199 kwoo
void send_packet(uint8_t cmd, uint8_t addr) {
143 189 kwoo
    rs485_send_byte(DELIM);
144 199 kwoo
    rs485_send_byte(addr);
145 189 kwoo
    rs485_send_byte(SERVER);
146
    rs485_send_byte(cmd);
147 199 kwoo
    rs485_send_byte(addr ^ SERVER ^ cmd);
148 189 kwoo
}
149
150 211 kwoo
/**
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
}