src/hp34comm.cpp

changeset 18
4fd621551d55
parent 16
c5e5bdc5ef49
child 19
a52d60613cf7
equal deleted inserted replaced
17:162fe523c37d 18:4fd621551d55
13 DigitalOut statetx(D10); 13 DigitalOut statetx(D10);
14 14
15 #endif 15 #endif
16 16
17 DigitalOut lled(LED1); 17 DigitalOut lled(LED1);
18
19 HPSerial::HPSerial(PinName rx):
20 serial_rx(NC, rx),
21 ncmd(0) {
22
23 //pc.printf("HPSerial init\n");
24 18
25 for(uint8_t i=0; i<MAX_ERRS; i++) 19
26 errs[i] = 0; 20
27 reset(); 21 HPSerial::HPSerial(PinName tx, PinName rx):
28 22 serial(tx, rx)
29 serial_rx.baud(187500); 23 {
30 serial_rx.attach(this, &HPSerial::rxIrq, Serial::RxIrq); 24 cur_state = do_state_initial(&rx_data, 0x00);
25 serial.baud(187500);
26 serial.attach(this, &HPSerial::rxIrq, Serial::RxIrq);
31 } 27 }
32 28
33 bool HPSerial::cmd_available(void) { 29 bool HPSerial::cmd_available(void) {
34 return !cmdbuf.empty(); 30 return !cmdbuf.empty();
35 } 31 }
43 } 39 }
44 40
45 unsigned int HPSerial::nerrors(uint8_t errorno) { 41 unsigned int HPSerial::nerrors(uint8_t errorno) {
46 return errs[errorno]; 42 return errs[errorno];
47 } 43 }
48
49
50
51 void HPSerial::reset(uint8_t errorno) {
52 timeouter.detach();
53 head = 0;
54 tx_state = Idle;
55 setstatedbg();
56 tx_cmd = 0xFF;
57 tx_ack = false;
58 tx_len = 0xFF;
59 memset(buf, 0, BUF_SIZE);
60 if (errorno != 0xFF){
61 errs[errorno]++;
62 }
63
64 }
65 44
66 void HPSerial::handleAck(uint8_t val) { 45 void HPSerial::pushCmd(uint8_t cmd, uint8_t size, char *payload) {
67 if ((tx_state == Rx) & (tx_cmd == 0xFF) & (tx_ack == false) & (val == 0x66)) {
68 // special case: keypad does not acknwledge and takes precedence
69 // on the "bus"
70 tx_state = Tx;
71 setstatedbg();
72 } else
73 if (tx_cmd == 0xFF) // beginning of a packet, expect 0x99 as ack
74 if (val == 0x99)
75 {
76 tx_ack = true;
77 #ifdef DEBUG2
78 ack = 1;
79 wait_us(2);
80 ack = 0;
81 #endif
82 }
83 else
84 reset(1);
85
86 else // expect 0x00 as ack
87 if (val == 0x00)
88 {
89 tx_ack = true;
90 #ifdef DEBUG2
91 ack = 1;
92 wait_us(2);
93 ack = 0;
94 #endif
95 }
96 else
97 reset(2);
98 }
99
100 void HPSerial::pushCmd(TrState direction, uint8_t cmd, uint8_t size, char *payload) {
101 CMD val; 46 CMD val;
102 uint8_t i; 47 uint8_t i;
103 val.id = ncmd++; 48 val.id = ncmd++;
104 val.direction = direction;
105 val.cmd = cmd; 49 val.cmd = cmd;
106 val.size = size; 50 val.size = size;
107 for(i=0; i<size; i++) 51 for(i=0; i<size; i++)
108 val.value[i] = payload[i]; 52 val.value[i] = payload[i];
109 val.value[i] = 0x00; 53 val.value[i] = 0x00;
110 cmdbuf.push(val); 54 cmdbuf.push(val);
111 } 55 }
112 56
113 void HPSerial::handleChar(uint8_t val) { 57 void HPSerial::send_ack(uint8_t c) {
114 if (tx_ack == false) 58 timeouter.attach(this, &HPSerial::timeout, 0.001); // if nothing else happen in the next ms, reset
115 reset(3); 59 serial.putc(c);
116 else // remaining of the state machine
117 if (tx_cmd == 0xFF) {
118 // begin of transmission, expect a cmd
119 tx_cmd = val;
120 tx_ack = false;
121 tx_len = 0xFF;
122 }
123 else if (tx_len == 0xFF) {
124 if (val == 0x55) {
125 // packet was in fact a keystroke, tx_cmd is in fact the key
126 // stroke and no payload is expected
127 #ifdef DEBUG2
128 statetx = 1;
129 #endif
130 pushCmd((TrState)Tx, tx_cmd, 0, (char*)buf);
131 #ifdef DEBUG2
132 wait_us(2);
133 statetx = 0;
134 #endif
135 reset();
136 } else {
137 // got a cmd, expect a payload size
138 tx_len = val;
139 tx_ack = false;
140 }
141 }
142 else if (tx_len == 0x55) {
143 // packet was in fact a keystroke, tx_cmd is in fact the key
144 // stroke and no payload is expected
145 #ifdef DEBUG2
146 statetx = 1;
147 #endif
148 pushCmd((TrState)Tx, tx_cmd, 0, (char*)buf);
149 #ifdef DEBUG2
150 wait_us(2);
151 statetx = 0;
152 #endif
153 reset();
154 }
155 else if (tx_len > 0) {
156 // a payload char
157 buf[head++] = val;
158 tx_len--;
159 tx_ack = false;
160 }
161 else { // end of payload, manage sent content
162 uint8_t cur_state = tx_state;
163 pushCmd((TrState)tx_state, tx_cmd, head, (char*)buf);
164
165 switch(val) {
166 case 0x66: // a new transmisson
167 reset();
168 tx_state = cur_state;
169 setstatedbg();
170 break;
171 case 0x55:
172 reset();
173 break;
174 default:
175 reset(6);
176 break;
177 }
178 }
179 } 60 }
180 61
62 HPSerial::state_t HPSerial::do_state_initial(HPSerial::instance_data_t *data,
63 uint8_t c)
64 {
65 // go back to initial state
66 data->cmd = 0xFF;
67 data->size = 0;
68 data->received = 0;
69 timeouter.detach();
70 return HPSerial::STATE_IDLE;
71 }
181 72
73 HPSerial::state_t HPSerial::do_state_handcheck(HPSerial::instance_data_t *data,
74 uint8_t c)
75 {
76 // we are idle, incoming char is a handcheck
77 // knwon handcheck values are 0x66 and 0x33
78 switch (c) {
79 case 0x33:
80 send_ack(0xCC);
81 return HPSerial::STATE_PAYLOAD_SIZE;
82 break;
83 case 0x66:
84 send_ack(0x99);
85 return HPSerial::STATE_COMMAND;
86 break;
87 default:
88 return do_state_initial(data, 0x00);
89 }
90 }
182 91
183 void HPSerial::setstatedbg(void) { 92 HPSerial::state_t HPSerial::do_state_command(HPSerial::instance_data_t *data,
184 #ifdef DEBUG2 93 uint8_t c)
185 if (tx_state == Rx) 94 {
186 staterx = 1; 95 if (c == 0x55) { // EoT
187 else 96 return do_state_initial(data, 0x00);
188 staterx = 0; 97 }
189 if (tx_state == Tx) 98
190 statetx = 1; 99 data->cmd = c;
191 else 100 data->size = 0;
192 statetx = 0; 101 send_ack(0x00);
193 #endif 102 return HPSerial::STATE_PAYLOAD_SIZE;
194 } 103 }
104
105 HPSerial::state_t HPSerial::do_state_payload_size(HPSerial::instance_data_t *data,
106 uint8_t c)
107 {
108 data->size = c;
109 data->received = 0;
110 send_ack(0x00);
111 return HPSerial::STATE_PAYLOAD;
112 }
113
114 HPSerial::state_t HPSerial::do_state_payload(HPSerial::instance_data_t *data,
115 uint8_t c)
116 {
117 data->payload[data->received++] = c;
118 send_ack(0x00);
119 if (data->received >= data->size) {
120 pushCmd(data->cmd, data->size, data->payload);
121 return HPSerial::STATE_COMMAND;
122 }
123 return HPSerial::STATE_PAYLOAD;
124 }
125
126 HPSerial::state_t HPSerial::run_state(HPSerial::state_t cur_state,
127 HPSerial::instance_data_t *data,
128 uint8_t c)
129 {
130 return (this->*(HPSerial::state_table[cur_state]))(data, c);
131 };
195 132
196 void HPSerial::rxIrq(void) { 133 void HPSerial::rxIrq(void) {
197 uint8_t val; 134 uint8_t val;
198 if(serial_rx.readable()) { // no reason why we would end here without this condition, but hey 135 if(serial.readable()) { // no reason why we would end here without
136 // this condition, but hey
199 #ifdef DEBUG2 137 #ifdef DEBUG2
200 inrx=1; 138 inrx=1;
201 #endif 139 #endif
202 lled = 1; 140 lled = 1;
203 val = serial_rx.getc(); 141 val = serial.getc();
204 142 cur_state = run_state(cur_state, &rx_data, val);
205 timeouter.attach(this, &HPSerial::timeout, 0.001); // if nothing else happen in the next ms, reset
206
207 if (tx_state == Idle)
208 if (val == 0x66) {
209 // no transmission in progress, expect a start of transmission
210 tx_state = Rx;
211 tx_ack = false;
212 setstatedbg();
213 }
214 else {
215 reset(4);
216 }
217 else if (tx_ack == false) // manage the acks
218 handleAck(val);
219 else
220 handleChar(val);
221 lled = 0; 143 lled = 0;
222 #ifdef DEBUG2 144 #ifdef DEBUG2
223 inrx=0; 145 inrx=0;
224 #endif 146 #endif
225 } 147 }
226 } 148 }
227 149
228 150
229 void HPSerial::timeout(void) { 151 void HPSerial::timeout(void) {
230 if (tx_state != Idle) { 152 cur_state = do_state_initial(&rx_data, 0x00);
231 reset(7);
232 }
233 } 153 }

mercurial