Project

General

Profile

Statistics
| Revision:

root / trunk / bootloader / packet.c @ 209

History | View | Annotate | Download (3.43 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 {
104
                state = cs;
105
            }
106
            break;
107

    
108
        case read:
109
            mbuf[pos] = r;
110
            crc ^= r;
111
            pos++;
112

    
113
            if (pos == lim) {
114
                state = cs;
115
            }
116

    
117
            break;
118
       
119
        case cs:
120
            if (r == crc) {
121
                if (cmd == TT_RESET) {
122
                    reset();
123
                }
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