Small bugfix in randomatic
[cerebrum.git] / avr / soft-iso14543-3-6.c.tp
blob7d07fbcad7dae0d92e3e1fca3a8f891a4f93b39e
2 #ifndef _SOFT_ISO14543_3_6_
3 #define _SOFT_ISO14543_3_6_
5 //I kind of hate the person concocting this control field. On the other hand, it is probably the result of the work (I won't say collaboration) of a number of persons equal to the population of a small country.
6 typedef struct {                                //Control field, always the first byte
7         unsigned char ft:1;                     //Frame type: 0 - extended/poll; 1 - standard
8         unsigned char poll: 1;          //Poll frame - 1; otherwise 0
9                                                                 //ft/poll are used in ack frames as follows: ack/busy 11, nack/nack+busy 00
10         unsigned char r: 1;                     //Repeat flag: 0 - repeated frame/ack frame; 1 - not repeated frame/poll frame
11         unsigned char ack: 1;           //Ack frame - 0; otherwise 1
12         unsigned char priority: 2;      //Priority: system/poll 0, urgent 2, normal 1, low 3
13                                                                 // if this is an ack frame: ack/nack 3, busy/nack+busy 0
14         unsigned char _: 2;                     //Padding, always 00
15 } iso14543_3_6_frame_ctrl; //1 byte
17 typedef struct {
18         unsigned char at:1;                     //Destination address type: physical/individual - 0; group - 1
19         unsigned char hops:3;           //Hop count
20         unsigned char eff:4;            //Extended frame format: default 0, LTE-HEE extended address type 01xx
21 } iso14543_3_6_frame_ctrle; //1 byte
23 typedef union {
24         unsigned int i16;
25         struct {                                //Physical address
26                 unsigned char area:4;           //Area
27                 unsigned char line:4;           //Line
28                 unsigned char device;           //Device
29         };
30 } iso14543_3_6_frame_address; //1 word
32 //XXX The following frame definitions are missing the checksum because that is generated and checked on the fly during rx/tx.
33 //"unsigned char checksum;"                     //xor all bytes of the frame, invert.
34 //Also, please note that where I'm talking about bytes, the iso norm talks about "octets".
36 //Structure of a iso14543-3-6 TP1 standard frame
37 typedef struct {
38         iso14543_3_6_frame_address sa;  //Source address
39         iso14543_3_6_frame_address da;  //Destination address
40         struct aux {                                    //Various flags
41                 unsigned char at:1;                     //Destination address type: physical/individual - 0; group - 1
42                 unsigned char hops:3;           //Hop count
43                 unsigned char len:4;            //Payload length
44         }; //1 byte
45         unsigned char payload[15];
46 } iso14543_3_6_std_frame;
48 //Structure of a iso14543-3-6 TP1 extended frame
49 typedef struct {
50         iso14543_3_6_frame_ctrle;               //Extended control field (only present in -- you guessed it, extended frames)
51         iso14543_3_6_frame_address sa;  //Source address
52         iso14543_3_6_frame_address da;  //Destination address
53         unsigned char len;                              //Payload length (0xFF is an escape code)
54         unsigned char payload[255];
55 } iso14543_3_6_ext_frame;
57 //Structure of a iso14543-3-6 TP1 poll frame
58 typedef struct {
59         iso14543_3_6_frame_address sa;  //Source address
60         uint16_t da;                                    //Poll group address
61         struct aux { //strange aux byte
62                 unsigned char _:4;                      //Padding (0000)
63                 unsigned char len:4;            //Number of poll responses expected
64         }
65 } iso14543_3_6_poll_frame;
67 //Structure of a generic iso14543-3-6 TP1 frame
68 typedef struct {
69         iso14543_3_6_frame_ctrl ctrl;           //1 byte (if it's an ack sent w/o checksum)
70         union {
71                 iso14543_3_6_std_frame  std;    //5-20 byte (+1 checksum)
72                 iso14543_3_6_ext_frame  ext;    //6-261 byte (+1 checksum)
73                 iso14543_3_6_poll_frame poll;   //5 byte (+1 checksum)
74         }
75         unsigned char checksum;
76 } iso14543_3_6_frame;
78 #endif//_SOFT_ISO14543_3_6_
80 ${modulevar("frame", "iso14543_3_6_frame", "BHHB255sB", set_action=modulevar("frame")+"_set_action")};
81 ${modulevar("extende_frame", None, "BBHHB255sB")};
83 void callback_set_${modulevar("extended_frame")}(uint16_t payload_offset, uint16_t alen, uint8_t* argbuf){
84         callback_set_${modulevar("frame")}(payload_offset, alen, argbuf);
87 void callback_get_${modulevar("extended_frame")}(uint16_t payload_offset, uint16_t alen, uint8_t* argbuf){
88         callback_set_${modulevar("frame")}(payload_offset, alen, argbuf);
91 volatile unsigned char ${modulevar("status")} = 0;
92 unsigned char* ${modulevar("endptr")} = 0;
94 void ${init_function()} (void){
95         DDR${member["tx"]["port"]} |= (1<<${member["tx"]["pin"]});
96         //set up pin change interrupt
99 //XXX This module uses pin change interrupts since the pulses it tries to detect are only 34µs long (@16MHz ~= 512 cycles)
100 //XXX This module uses one 16-bit timer
101 //The timer is clocked with a 16934400Hz system clock overflows every 588 cycles. A bit is over every 1764 cycles.
102 //The error of this timing is less than 1% compared to a 9600Bd reference.
104 //Returns 0 on success, other stuff when an error occurs.
105 char ${modulevar("frame")_send_next_bit(){
106         static unsigned char bit = 0;
107         static unsigned char data = 0;
108         static unsigned char *pos = 0;
109         char res = 0;
111         bit++;
112         if(bit == 8){
113                 bit = 0;
115                 ${modulevar("frame")}.checksum ^= data;
117                 pos++;
118                 if(pos > ${modulevar("endptr")}){
119                         if(pos > &(${modulevar("frame")}.checksum)){ //End of frame, checksum sent
120                                 pos = &(${modulevar("frame")}.ctrl);
121                                 bit = 8;
122                                 res = -33;
123                         }else{ //End of frame, send checksum
124                                 ${modulevar("frame")}.checksum ^= 0xFF; //Invert
125                                 pos = &(${modulevar("frame")}.checksum);
126                         }
127                 }
129                 data = *pos;
130         }
132         unsigned char nd = data << 1;
133         if(nd < data){ //msb set
134                 // i.e. (data * 2) mod 256 < data
135                 // unsigned char => 0 < data < 256
136                 // data < 128:
137                 //   data * 2 < data => false
138                 // data >= 128:
139                 //   data * 2 - 256 == data + data - 256 < data - 1 < data
140                 //send logic 1: leave the bus alone
141                 res |= 1;
142         }else{
143                 //send logic 0: short the bus
144                 port${member["tx"]["port"]} |= (1<<${member["tx"]["pin"]});
145                 res &= ~1;
146         }
147         data = nd;
149         return res;
152 ISR(/*FIXME*/){ //Timer overflow @ 1/3 cycle
153         static unsigned char cnt = 0;
154         unsigned char e = 0;
155         cnt++;
156         if(cnt == 3){
157                 cnt = 0;
158                 unsigned char state = ${modulevar("state")};
159                 if(state >= 0){ //Data transfer in progress
160                         ${modulevar("state")} = ${modulevar("frame")}_send_next_bit();
161                 }else if(state < -33){
162                         state--; //Decrement timeout before initiation of new bus action
163                 }
164         }else{
165                 PORT${member["tx"]["port"]} &= ~(1<<${member["tx"]["pin"]});
166         }
169 ISR(/*FIXME*/){ //PCInt
170         if(/*pin check*/){
171                 if(${modulevar("state") >= 0){ //Currently transmitting
172                         if(!(${modulevar("state")}&1) && !!(/*input pin state*/)){ //If a 1 is on the wire although none was sent
173                                 //Collision! Idle for 50 cycles, retry.
174                                 ${modulevar("state")} = -33-50; //Prevent the transmission of any further bits
175                         }
176                 }else{
177                         if(modulevar("state") == -33){ //Idle
178                                 //Somebody else is sending. Set a timeout for 53 cycles.
179                                 ${modulevar("state")} = -33-53; //Prevent the transmission a frame
180                         }
181                 }
182         }
185 //add pin change interrupt vector
187 void ${modulevar("frame")}_set_action (void){
188         iso14543_3_6_frame* f = &${modulevar("frame")};
190         f->checksum = 0;
191         if(!f->ctrl.poll ){
192                 if( !f->ctrl.ft ){ //Extended frame
193                         ${modulevar("endptr")} = &(f->ext.len) + f->ext.len;
194                 }else{ //Standard frame
195                         ${modulevar("endptr")} = &(f->std.aux) + f->std.len;
196                 }
197         }else{ //Poll frame
198                 ${modulevar("endptr")} = &(f->poll.aux);
199         }
200         
201         ${modulevar("state")} = 2;