Project

General

Profile

Statistics
| Revision:

root / trunk / bootloader / packet.c @ 287

History | View | Annotate | Download (3.79 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
    plen,
19
    read, 
20
    cs    
21
} state_t;
22

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

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

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

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

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

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

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

    
96
            if (r == DELIM) {
97
                state = src;
98
            } else {
99
                state = plen;
100
            }
101
            break;
102
        case plen:
103
            lim = r;
104
            crc ^= r;
105
            *len = r;
106

    
107
            if (r == 0) {
108
                state = cs;
109
            } else {
110
                state = read;
111
            }
112
            break;
113
        case read:
114
            mbuf[pos] = r;
115
            crc ^= r;
116
            pos++;
117

    
118
            if (pos == lim) {
119
                state = cs;
120
            }
121
            break;
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
 * @param data Pointer to data
145
 * @param len Number of bytes to send
146
 */
147
void send_packet(uint8_t cmd, uint8_t addr, uint8_t* data, uint8_t len) {
148
    uint8_t i;
149
    uint8_t crc = 0;
150

    
151
    rs485_toggle_transmit(RS485_TX_ON);
152
    rs485_send_byte(DELIM);
153
    rs485_send_byte(addr);
154
    rs485_send_byte(SERVER);
155
    rs485_send_byte(cmd);
156
    rs485_send_byte(len);
157
    for (i=0; i < len; i++) {
158
        crc  ^= data[i];
159
        rs485_send_byte(data[i]);
160
    }
161
    rs485_send_byte(addr ^ SERVER ^ len ^ cmd ^ crc);
162
    rs485_toggle_transmit(RS485_TX_OFF);
163
}
164