aboutsummaryrefslogtreecommitdiff
path: root/quantum/serial_link/protocol
diff options
context:
space:
mode:
Diffstat (limited to 'quantum/serial_link/protocol')
-rw-r--r--quantum/serial_link/protocol/byte_stuffer.c145
-rw-r--r--quantum/serial_link/protocol/byte_stuffer.h34
-rw-r--r--quantum/serial_link/protocol/frame_router.c69
-rw-r--r--quantum/serial_link/protocol/frame_router.h38
-rw-r--r--quantum/serial_link/protocol/frame_validator.c121
-rw-r--r--quantum/serial_link/protocol/frame_validator.h34
-rw-r--r--quantum/serial_link/protocol/physical.h30
-rw-r--r--quantum/serial_link/protocol/transport.c124
-rw-r--r--quantum/serial_link/protocol/transport.h151
-rw-r--r--quantum/serial_link/protocol/triple_buffered_object.c78
-rw-r--r--quantum/serial_link/protocol/triple_buffered_object.h51
11 files changed, 875 insertions, 0 deletions
diff --git a/quantum/serial_link/protocol/byte_stuffer.c b/quantum/serial_link/protocol/byte_stuffer.c
new file mode 100644
index 000000000..fb4c45a8d
--- /dev/null
+++ b/quantum/serial_link/protocol/byte_stuffer.c
@@ -0,0 +1,145 @@
1/*
2The MIT License (MIT)
3
4Copyright (c) 2016 Fred Sundvik
5
6Permission is hereby granted, free of charge, to any person obtaining a copy
7of this software and associated documentation files (the "Software"), to deal
8in the Software without restriction, including without limitation the rights
9to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10copies of the Software, and to permit persons to whom the Software is
11furnished to do so, subject to the following conditions:
12
13The above copyright notice and this permission notice shall be included in all
14copies or substantial portions of the Software.
15
16THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22SOFTWARE.
23*/
24
25#include "serial_link/protocol/byte_stuffer.h"
26#include "serial_link/protocol/frame_validator.h"
27#include "serial_link/protocol/physical.h"
28#include <stdbool.h>
29
30// This implements the "Consistent overhead byte stuffing protocol"
31// https://en.wikipedia.org/wiki/Consistent_Overhead_Byte_Stuffing
32// http://www.stuartcheshire.org/papers/COBSforToN.pdf
33
34#define MAX_FRAME_SIZE 1024
35#define NUM_LINKS 2
36
37typedef struct byte_stuffer_state {
38 uint16_t next_zero;
39 uint16_t data_pos;
40 bool long_frame;
41 uint8_t data[MAX_FRAME_SIZE];
42}byte_stuffer_state_t;
43
44static byte_stuffer_state_t states[NUM_LINKS];
45
46void init_byte_stuffer_state(byte_stuffer_state_t* state) {
47 state->next_zero = 0;
48 state->data_pos = 0;
49 state->long_frame = false;
50}
51
52void init_byte_stuffer(void) {
53 int i;
54 for (i=0;i<NUM_LINKS;i++) {
55 init_byte_stuffer_state(&states[i]);
56 }
57}
58
59void byte_stuffer_recv_byte(uint8_t link, uint8_t data) {
60 byte_stuffer_state_t* state = &states[link];
61 // Start of a new frame
62 if (state->next_zero == 0) {
63 state->next_zero = data;
64 state->long_frame = data == 0xFF;
65 state->data_pos = 0;
66 return;
67 }
68
69 state->next_zero--;
70 if (data == 0) {
71 if (state->next_zero == 0) {
72 // The frame is completed
73 if (state->data_pos > 0) {
74 validator_recv_frame(link, state->data, state->data_pos);
75 }
76 }
77 else {
78 // The frame is invalid, so reset
79 init_byte_stuffer_state(state);
80 }
81 }
82 else {
83 if (state->data_pos == MAX_FRAME_SIZE) {
84 // We exceeded our maximum frame size
85 // therefore there's nothing else to do than reset to a new frame
86 state->next_zero = data;
87 state->long_frame = data == 0xFF;
88 state->data_pos = 0;
89 }
90 else if (state->next_zero == 0) {
91 if (state->long_frame) {
92 // This is part of a long frame, so continue
93 state->next_zero = data;
94 state->long_frame = data == 0xFF;
95 }
96 else {
97 // Special case for zeroes
98 state->next_zero = data;
99 state->data[state->data_pos++] = 0;
100 }
101 }
102 else {
103 state->data[state->data_pos++] = data;
104 }
105 }
106}
107
108static void send_block(uint8_t link, uint8_t* start, uint8_t* end, uint8_t num_non_zero) {
109 send_data(link, &num_non_zero, 1);
110 if (end > start) {
111 send_data(link, start, end-start);
112 }
113}
114
115void byte_stuffer_send_frame(uint8_t link, uint8_t* data, uint16_t size) {
116 const uint8_t zero = 0;
117 if (size > 0) {
118 uint16_t num_non_zero = 1;
119 uint8_t* end = data + size;
120 uint8_t* start = data;
121 while (data < end) {
122 if (num_non_zero == 0xFF) {
123 // There's more data after big non-zero block
124 // So send it, and start a new block
125 send_block(link, start, data, num_non_zero);
126 start = data;
127 num_non_zero = 1;
128 }
129 else {
130 if (*data == 0) {
131 // A zero encountered, so send the block
132 send_block(link, start, data, num_non_zero);
133 start = data + 1;
134 num_non_zero = 1;
135 }
136 else {
137 num_non_zero++;
138 }
139 ++data;
140 }
141 }
142 send_block(link, start, data, num_non_zero);
143 send_data(link, &zero, 1);
144 }
145}
diff --git a/quantum/serial_link/protocol/byte_stuffer.h b/quantum/serial_link/protocol/byte_stuffer.h
new file mode 100644
index 000000000..2cc88beb4
--- /dev/null
+++ b/quantum/serial_link/protocol/byte_stuffer.h
@@ -0,0 +1,34 @@
1/*
2The MIT License (MIT)
3
4Copyright (c) 2016 Fred Sundvik
5
6Permission is hereby granted, free of charge, to any person obtaining a copy
7of this software and associated documentation files (the "Software"), to deal
8in the Software without restriction, including without limitation the rights
9to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10copies of the Software, and to permit persons to whom the Software is
11furnished to do so, subject to the following conditions:
12
13The above copyright notice and this permission notice shall be included in all
14copies or substantial portions of the Software.
15
16THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22SOFTWARE.
23*/
24
25#ifndef SERIAL_LINK_BYTE_STUFFER_H
26#define SERIAL_LINK_BYTE_STUFFER_H
27
28#include <stdint.h>
29
30void init_byte_stuffer(void);
31void byte_stuffer_recv_byte(uint8_t link, uint8_t data);
32void byte_stuffer_send_frame(uint8_t link, uint8_t* data, uint16_t size);
33
34#endif
diff --git a/quantum/serial_link/protocol/frame_router.c b/quantum/serial_link/protocol/frame_router.c
new file mode 100644
index 000000000..04b8c2e75
--- /dev/null
+++ b/quantum/serial_link/protocol/frame_router.c
@@ -0,0 +1,69 @@
1/*
2The MIT License (MIT)
3
4Copyright (c) 2016 Fred Sundvik
5
6Permission is hereby granted, free of charge, to any person obtaining a copy
7of this software and associated documentation files (the "Software"), to deal
8in the Software without restriction, including without limitation the rights
9to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10copies of the Software, and to permit persons to whom the Software is
11furnished to do so, subject to the following conditions:
12
13The above copyright notice and this permission notice shall be included in all
14copies or substantial portions of the Software.
15
16THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22SOFTWARE.
23*/
24
25#include "serial_link/protocol/frame_router.h"
26#include "serial_link/protocol/transport.h"
27#include "serial_link/protocol/frame_validator.h"
28
29static bool is_master;
30
31void router_set_master(bool master) {
32 is_master = master;
33}
34
35void route_incoming_frame(uint8_t link, uint8_t* data, uint16_t size){
36 if (is_master) {
37 if (link == DOWN_LINK) {
38 transport_recv_frame(data[size-1], data, size - 1);
39 }
40 }
41 else {
42 if (link == UP_LINK) {
43 if (data[size-1] & 1) {
44 transport_recv_frame(0, data, size - 1);
45 }
46 data[size-1] >>= 1;
47 validator_send_frame(DOWN_LINK, data, size);
48 }
49 else {
50 data[size-1]++;
51 validator_send_frame(UP_LINK, data, size);
52 }
53 }
54}
55
56void router_send_frame(uint8_t destination, uint8_t* data, uint16_t size) {
57 if (destination == 0) {
58 if (!is_master) {
59 data[size] = 1;
60 validator_send_frame(UP_LINK, data, size + 1);
61 }
62 }
63 else {
64 if (is_master) {
65 data[size] = destination;
66 validator_send_frame(DOWN_LINK, data, size + 1);
67 }
68 }
69}
diff --git a/quantum/serial_link/protocol/frame_router.h b/quantum/serial_link/protocol/frame_router.h
new file mode 100644
index 000000000..712250ff3
--- /dev/null
+++ b/quantum/serial_link/protocol/frame_router.h
@@ -0,0 +1,38 @@
1/*
2The MIT License (MIT)
3
4Copyright (c) 2016 Fred Sundvik
5
6Permission is hereby granted, free of charge, to any person obtaining a copy
7of this software and associated documentation files (the "Software"), to deal
8in the Software without restriction, including without limitation the rights
9to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10copies of the Software, and to permit persons to whom the Software is
11furnished to do so, subject to the following conditions:
12
13The above copyright notice and this permission notice shall be included in all
14copies or substantial portions of the Software.
15
16THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22SOFTWARE.
23*/
24
25#ifndef SERIAL_LINK_FRAME_ROUTER_H
26#define SERIAL_LINK_FRAME_ROUTER_H
27
28#include <stdint.h>
29#include <stdbool.h>
30
31#define UP_LINK 0
32#define DOWN_LINK 1
33
34void router_set_master(bool master);
35void route_incoming_frame(uint8_t link, uint8_t* data, uint16_t size);
36void router_send_frame(uint8_t destination, uint8_t* data, uint16_t size);
37
38#endif
diff --git a/quantum/serial_link/protocol/frame_validator.c b/quantum/serial_link/protocol/frame_validator.c
new file mode 100644
index 000000000..474f80ee8
--- /dev/null
+++ b/quantum/serial_link/protocol/frame_validator.c
@@ -0,0 +1,121 @@
1/*
2The MIT License (MIT)
3
4Copyright (c) 2016 Fred Sundvik
5
6Permission is hereby granted, free of charge, to any person obtaining a copy
7of this software and associated documentation files (the "Software"), to deal
8in the Software without restriction, including without limitation the rights
9to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10copies of the Software, and to permit persons to whom the Software is
11furnished to do so, subject to the following conditions:
12
13The above copyright notice and this permission notice shall be included in all
14copies or substantial portions of the Software.
15
16THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22SOFTWARE.
23*/
24
25#include "serial_link/protocol/frame_validator.h"
26#include "serial_link/protocol/frame_router.h"
27#include "serial_link/protocol/byte_stuffer.h"
28#include <string.h>
29
30const uint32_t poly8_lookup[256] =
31{
32 0, 0x77073096, 0xEE0E612C, 0x990951BA,
33 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,
34 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988,
35 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91,
36 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE,
37 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
38 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC,
39 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5,
40 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172,
41 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B,
42 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940,
43 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
44 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116,
45 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
46 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924,
47 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D,
48 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A,
49 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
50 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818,
51 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01,
52 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E,
53 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457,
54 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C,
55 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
56 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2,
57 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB,
58 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0,
59 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,
60 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086,
61 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
62 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4,
63 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD,
64 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A,
65 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683,
66 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8,
67 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
68 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE,
69 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7,
70 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC,
71 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5,
72 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252,
73 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
74 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60,
75 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79,
76 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236,
77 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F,
78 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04,
79 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
80 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A,
81 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713,
82 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38,
83 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21,
84 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E,
85 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
86 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C,
87 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,
88 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2,
89 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB,
90 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0,
91 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
92 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6,
93 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF,
94 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94,
95 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
96};
97
98static uint32_t crc32_byte(uint8_t *p, uint32_t bytelength)
99{
100 uint32_t crc = 0xffffffff;
101 while (bytelength-- !=0) crc = poly8_lookup[((uint8_t) crc ^ *(p++))] ^ (crc >> 8);
102 // return (~crc); also works
103 return (crc ^ 0xffffffff);
104}
105
106void validator_recv_frame(uint8_t link, uint8_t* data, uint16_t size) {
107 if (size > 4) {
108 uint32_t frame_crc;
109 memcpy(&frame_crc, data + size -4, 4);
110 uint32_t expected_crc = crc32_byte(data, size - 4);
111 if (frame_crc == expected_crc) {
112 route_incoming_frame(link, data, size-4);
113 }
114 }
115}
116
117void validator_send_frame(uint8_t link, uint8_t* data, uint16_t size) {
118 uint32_t crc = crc32_byte(data, size);
119 memcpy(data + size, &crc, 4);
120 byte_stuffer_send_frame(link, data, size + 4);
121}
diff --git a/quantum/serial_link/protocol/frame_validator.h b/quantum/serial_link/protocol/frame_validator.h
new file mode 100644
index 000000000..4a910d510
--- /dev/null
+++ b/quantum/serial_link/protocol/frame_validator.h
@@ -0,0 +1,34 @@
1/*
2The MIT License (MIT)
3
4Copyright (c) 2016 Fred Sundvik
5
6Permission is hereby granted, free of charge, to any person obtaining a copy
7of this software and associated documentation files (the "Software"), to deal
8in the Software without restriction, including without limitation the rights
9to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10copies of the Software, and to permit persons to whom the Software is
11furnished to do so, subject to the following conditions:
12
13The above copyright notice and this permission notice shall be included in all
14copies or substantial portions of the Software.
15
16THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22SOFTWARE.
23*/
24
25#ifndef SERIAL_LINK_FRAME_VALIDATOR_H
26#define SERIAL_LINK_FRAME_VALIDATOR_H
27
28#include <stdint.h>
29
30void validator_recv_frame(uint8_t link, uint8_t* data, uint16_t size);
31// The buffer pointed to by the data needs 4 additional bytes
32void validator_send_frame(uint8_t link, uint8_t* data, uint16_t size);
33
34#endif
diff --git a/quantum/serial_link/protocol/physical.h b/quantum/serial_link/protocol/physical.h
new file mode 100644
index 000000000..425e06cdd
--- /dev/null
+++ b/quantum/serial_link/protocol/physical.h
@@ -0,0 +1,30 @@
1/*
2The MIT License (MIT)
3
4Copyright (c) 2016 Fred Sundvik
5
6Permission is hereby granted, free of charge, to any person obtaining a copy
7of this software and associated documentation files (the "Software"), to deal
8in the Software without restriction, including without limitation the rights
9to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10copies of the Software, and to permit persons to whom the Software is
11furnished to do so, subject to the following conditions:
12
13The above copyright notice and this permission notice shall be included in all
14copies or substantial portions of the Software.
15
16THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22SOFTWARE.
23*/
24
25#ifndef SERIAL_LINK_PHYSICAL_H
26#define SERIAL_LINK_PHYSICAL_H
27
28void send_data(uint8_t link, const uint8_t* data, uint16_t size);
29
30#endif
diff --git a/quantum/serial_link/protocol/transport.c b/quantum/serial_link/protocol/transport.c
new file mode 100644
index 000000000..f418d11ce
--- /dev/null
+++ b/quantum/serial_link/protocol/transport.c
@@ -0,0 +1,124 @@
1/*
2The MIT License (MIT)
3
4Copyright (c) 2016 Fred Sundvik
5
6Permission is hereby granted, free of charge, to any person obtaining a copy
7of this software and associated documentation files (the "Software"), to deal
8in the Software without restriction, including without limitation the rights
9to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10copies of the Software, and to permit persons to whom the Software is
11furnished to do so, subject to the following conditions:
12
13The above copyright notice and this permission notice shall be included in all
14copies or substantial portions of the Software.
15
16THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22SOFTWARE.
23*/
24
25#include "serial_link/protocol/transport.h"
26#include "serial_link/protocol/frame_router.h"
27#include "serial_link/protocol/triple_buffered_object.h"
28#include <string.h>
29
30#define MAX_REMOTE_OBJECTS 16
31static remote_object_t* remote_objects[MAX_REMOTE_OBJECTS];
32static uint32_t num_remote_objects = 0;
33
34void add_remote_objects(remote_object_t** _remote_objects, uint32_t _num_remote_objects) {
35 unsigned int i;
36 for(i=0;i<_num_remote_objects;i++) {
37 remote_object_t* obj = _remote_objects[i];
38 remote_objects[num_remote_objects++] = obj;
39 if (obj->object_type == MASTER_TO_ALL_SLAVES) {
40 triple_buffer_object_t* tb = (triple_buffer_object_t*)obj->buffer;
41 triple_buffer_init(tb);
42 uint8_t* start = obj->buffer + LOCAL_OBJECT_SIZE(obj->object_size);
43 tb = (triple_buffer_object_t*)start;
44 triple_buffer_init(tb);
45 }
46 else if(obj->object_type == MASTER_TO_SINGLE_SLAVE) {
47 uint8_t* start = obj->buffer;
48 unsigned int j;
49 for (j=0;j<NUM_SLAVES;j++) {
50 triple_buffer_object_t* tb = (triple_buffer_object_t*)start;
51 triple_buffer_init(tb);
52 start += LOCAL_OBJECT_SIZE(obj->object_size);
53 }
54 triple_buffer_object_t* tb = (triple_buffer_object_t*)start;
55 triple_buffer_init(tb);
56 }
57 else {
58 uint8_t* start = obj->buffer;
59 triple_buffer_object_t* tb = (triple_buffer_object_t*)start;
60 triple_buffer_init(tb);
61 start += LOCAL_OBJECT_SIZE(obj->object_size);
62 unsigned int j;
63 for (j=0;j<NUM_SLAVES;j++) {
64 tb = (triple_buffer_object_t*)start;
65 triple_buffer_init(tb);
66 start += REMOTE_OBJECT_SIZE(obj->object_size);
67 }
68 }
69 }
70}
71
72void transport_recv_frame(uint8_t from, uint8_t* data, uint16_t size) {
73 uint8_t id = data[size-1];
74 if (id < num_remote_objects) {
75 remote_object_t* obj = remote_objects[id];
76 if (obj->object_size == size - 1) {
77 uint8_t* start;
78 if (obj->object_type == MASTER_TO_ALL_SLAVES) {
79 start = obj->buffer + LOCAL_OBJECT_SIZE(obj->object_size);
80 }
81 else if(obj->object_type == SLAVE_TO_MASTER) {
82 start = obj->buffer + LOCAL_OBJECT_SIZE(obj->object_size);
83 start += (from - 1) * REMOTE_OBJECT_SIZE(obj->object_size);
84 }
85 else {
86 start = obj->buffer + NUM_SLAVES * LOCAL_OBJECT_SIZE(obj->object_size);
87 }
88 triple_buffer_object_t* tb = (triple_buffer_object_t*)start;
89 void* ptr = triple_buffer_begin_write_internal(obj->object_size, tb);
90 memcpy(ptr, data, size - 1);
91 triple_buffer_end_write_internal(tb);
92 }
93 }
94}
95
96void update_transport(void) {
97 unsigned int i;
98 for(i=0;i<num_remote_objects;i++) {
99 remote_object_t* obj = remote_objects[i];
100 if (obj->object_type == MASTER_TO_ALL_SLAVES || obj->object_type == SLAVE_TO_MASTER) {
101 triple_buffer_object_t* tb = (triple_buffer_object_t*)obj->buffer;
102 uint8_t* ptr = (uint8_t*)triple_buffer_read_internal(obj->object_size + LOCAL_OBJECT_EXTRA, tb);
103 if (ptr) {
104 ptr[obj->object_size] = i;
105 uint8_t dest = obj->object_type == MASTER_TO_ALL_SLAVES ? 0xFF : 0;
106 router_send_frame(dest, ptr, obj->object_size + 1);
107 }
108 }
109 else {
110 uint8_t* start = obj->buffer;
111 unsigned int j;
112 for (j=0;j<NUM_SLAVES;j++) {
113 triple_buffer_object_t* tb = (triple_buffer_object_t*)start;
114 uint8_t* ptr = (uint8_t*)triple_buffer_read_internal(obj->object_size + LOCAL_OBJECT_EXTRA, tb);
115 if (ptr) {
116 ptr[obj->object_size] = i;
117 uint8_t dest = j + 1;
118 router_send_frame(dest, ptr, obj->object_size + 1);
119 }
120 start += LOCAL_OBJECT_SIZE(obj->object_size);
121 }
122 }
123 }
124}
diff --git a/quantum/serial_link/protocol/transport.h b/quantum/serial_link/protocol/transport.h
new file mode 100644
index 000000000..9a052d880
--- /dev/null
+++ b/quantum/serial_link/protocol/transport.h
@@ -0,0 +1,151 @@
1/*
2The MIT License (MIT)
3
4Copyright (c) 2016 Fred Sundvik
5
6Permission is hereby granted, free of charge, to any person obtaining a copy
7of this software and associated documentation files (the "Software"), to deal
8in the Software without restriction, including without limitation the rights
9to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10copies of the Software, and to permit persons to whom the Software is
11furnished to do so, subject to the following conditions:
12
13The above copyright notice and this permission notice shall be included in all
14copies or substantial portions of the Software.
15
16THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22SOFTWARE.
23*/
24
25#ifndef SERIAL_LINK_TRANSPORT_H
26#define SERIAL_LINK_TRANSPORT_H
27
28#include "serial_link/protocol/triple_buffered_object.h"
29#include "serial_link/system/serial_link.h"
30
31#define NUM_SLAVES 8
32#define LOCAL_OBJECT_EXTRA 16
33
34// master -> slave = 1 local(target all), 1 remote object
35// slave -> master = 1 local(target 0), multiple remote objects
36// master -> single slave (multiple local, target id), 1 remote object
37typedef enum {
38 MASTER_TO_ALL_SLAVES,
39 MASTER_TO_SINGLE_SLAVE,
40 SLAVE_TO_MASTER,
41} remote_object_type;
42
43typedef struct {
44 remote_object_type object_type;
45 uint16_t object_size;
46 uint8_t buffer[] __attribute__((aligned(4)));
47} remote_object_t;
48
49#define REMOTE_OBJECT_SIZE(objectsize) \
50 (sizeof(triple_buffer_object_t) + objectsize * 3)
51#define LOCAL_OBJECT_SIZE(objectsize) \
52 (sizeof(triple_buffer_object_t) + (objectsize + LOCAL_OBJECT_EXTRA) * 3)
53
54#define REMOTE_OBJECT_HELPER(name, type, num_local, num_remote) \
55typedef struct { \
56 remote_object_t object; \
57 uint8_t buffer[ \
58 num_remote * REMOTE_OBJECT_SIZE(sizeof(type)) + \
59 num_local * LOCAL_OBJECT_SIZE(sizeof(type))]; \
60} remote_object_##name##_t;
61
62#define MASTER_TO_ALL_SLAVES_OBJECT(name, type) \
63 REMOTE_OBJECT_HELPER(name, type, 1, 1) \
64 remote_object_##name##_t remote_object_##name = { \
65 .object = { \
66 .object_type = MASTER_TO_ALL_SLAVES, \
67 .object_size = sizeof(type), \
68 } \
69 }; \
70 type* begin_write_##name(void) { \
71 remote_object_t* obj = (remote_object_t*)&remote_object_##name; \
72 triple_buffer_object_t* tb = (triple_buffer_object_t*)obj->buffer; \
73 return (type*)triple_buffer_begin_write_internal(sizeof(type) + LOCAL_OBJECT_EXTRA, tb); \
74 }\
75 void end_write_##name(void) { \
76 remote_object_t* obj = (remote_object_t*)&remote_object_##name; \
77 triple_buffer_object_t* tb = (triple_buffer_object_t*)obj->buffer; \
78 triple_buffer_end_write_internal(tb); \
79 signal_data_written(); \
80 }\
81 type* read_##name(void) { \
82 remote_object_t* obj = (remote_object_t*)&remote_object_##name; \
83 uint8_t* start = obj->buffer + LOCAL_OBJECT_SIZE(obj->object_size);\
84 triple_buffer_object_t* tb = (triple_buffer_object_t*)start; \
85 return triple_buffer_read_internal(obj->object_size, tb); \
86 }
87
88#define MASTER_TO_SINGLE_SLAVE_OBJECT(name, type) \
89 REMOTE_OBJECT_HELPER(name, type, NUM_SLAVES, 1) \
90 remote_object_##name##_t remote_object_##name = { \
91 .object = { \
92 .object_type = MASTER_TO_SINGLE_SLAVE, \
93 .object_size = sizeof(type), \
94 } \
95 }; \
96 type* begin_write_##name(uint8_t slave) { \
97 remote_object_t* obj = (remote_object_t*)&remote_object_##name; \
98 uint8_t* start = obj->buffer;\
99 start += slave * LOCAL_OBJECT_SIZE(obj->object_size); \
100 triple_buffer_object_t* tb = (triple_buffer_object_t*)start; \
101 return (type*)triple_buffer_begin_write_internal(sizeof(type) + LOCAL_OBJECT_EXTRA, tb); \
102 }\
103 void end_write_##name(uint8_t slave) { \
104 remote_object_t* obj = (remote_object_t*)&remote_object_##name; \
105 uint8_t* start = obj->buffer;\
106 start += slave * LOCAL_OBJECT_SIZE(obj->object_size); \
107 triple_buffer_object_t* tb = (triple_buffer_object_t*)start; \
108 triple_buffer_end_write_internal(tb); \
109 signal_data_written(); \
110 }\
111 type* read_##name() { \
112 remote_object_t* obj = (remote_object_t*)&remote_object_##name; \
113 uint8_t* start = obj->buffer + NUM_SLAVES * LOCAL_OBJECT_SIZE(obj->object_size);\
114 triple_buffer_object_t* tb = (triple_buffer_object_t*)start; \
115 return triple_buffer_read_internal(obj->object_size, tb); \
116 }
117
118#define SLAVE_TO_MASTER_OBJECT(name, type) \
119 REMOTE_OBJECT_HELPER(name, type, 1, NUM_SLAVES) \
120 remote_object_##name##_t remote_object_##name = { \
121 .object = { \
122 .object_type = SLAVE_TO_MASTER, \
123 .object_size = sizeof(type), \
124 } \
125 }; \
126 type* begin_write_##name(void) { \
127 remote_object_t* obj = (remote_object_t*)&remote_object_##name; \
128 triple_buffer_object_t* tb = (triple_buffer_object_t*)obj->buffer; \
129 return (type*)triple_buffer_begin_write_internal(sizeof(type) + LOCAL_OBJECT_EXTRA, tb); \
130 }\
131 void end_write_##name(void) { \
132 remote_object_t* obj = (remote_object_t*)&remote_object_##name; \
133 triple_buffer_object_t* tb = (triple_buffer_object_t*)obj->buffer; \
134 triple_buffer_end_write_internal(tb); \
135 signal_data_written(); \
136 }\
137 type* read_##name(uint8_t slave) { \
138 remote_object_t* obj = (remote_object_t*)&remote_object_##name; \
139 uint8_t* start = obj->buffer + LOCAL_OBJECT_SIZE(obj->object_size);\
140 start+=slave * REMOTE_OBJECT_SIZE(obj->object_size); \
141 triple_buffer_object_t* tb = (triple_buffer_object_t*)start; \
142 return triple_buffer_read_internal(obj->object_size, tb); \
143 }
144
145#define REMOTE_OBJECT(name) (remote_object_t*)&remote_object_##name
146
147void add_remote_objects(remote_object_t** remote_objects, uint32_t num_remote_objects);
148void transport_recv_frame(uint8_t from, uint8_t* data, uint16_t size);
149void update_transport(void);
150
151#endif
diff --git a/quantum/serial_link/protocol/triple_buffered_object.c b/quantum/serial_link/protocol/triple_buffered_object.c
new file mode 100644
index 000000000..e3e8989d3
--- /dev/null
+++ b/quantum/serial_link/protocol/triple_buffered_object.c
@@ -0,0 +1,78 @@
1/*
2The MIT License (MIT)
3
4Copyright (c) 2016 Fred Sundvik
5
6Permission is hereby granted, free of charge, to any person obtaining a copy
7of this software and associated documentation files (the "Software"), to deal
8in the Software without restriction, including without limitation the rights
9to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10copies of the Software, and to permit persons to whom the Software is
11furnished to do so, subject to the following conditions:
12
13The above copyright notice and this permission notice shall be included in all
14copies or substantial portions of the Software.
15
16THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22SOFTWARE.
23*/
24
25#include "serial_link/protocol/triple_buffered_object.h"
26#include "serial_link/system/serial_link.h"
27#include <stdbool.h>
28#include <stddef.h>
29
30#define GET_READ_INDEX() object->state & 3
31#define GET_WRITE_INDEX() (object->state >> 2) & 3
32#define GET_SHARED_INDEX() (object->state >> 4) & 3
33#define GET_DATA_AVAILABLE() (object->state >> 6) & 1
34
35#define SET_READ_INDEX(i) object->state = ((object->state & ~3) | i)
36#define SET_WRITE_INDEX(i) object->state = ((object->state & ~(3 << 2)) | (i << 2))
37#define SET_SHARED_INDEX(i) object->state = ((object->state & ~(3 << 4)) | (i << 4))
38#define SET_DATA_AVAILABLE(i) object->state = ((object->state & ~(1 << 6)) | (i << 6))
39
40void triple_buffer_init(triple_buffer_object_t* object) {
41 object->state = 0;
42 SET_WRITE_INDEX(0);
43 SET_READ_INDEX(1);
44 SET_SHARED_INDEX(2);
45 SET_DATA_AVAILABLE(0);
46}
47
48void* triple_buffer_read_internal(uint16_t object_size, triple_buffer_object_t* object) {
49 serial_link_lock();
50 if (GET_DATA_AVAILABLE()) {
51 uint8_t shared_index = GET_SHARED_INDEX();
52 uint8_t read_index = GET_READ_INDEX();
53 SET_READ_INDEX(shared_index);
54 SET_SHARED_INDEX(read_index);
55 SET_DATA_AVAILABLE(false);
56 serial_link_unlock();
57 return object->buffer + object_size * shared_index;
58 }
59 else {
60 serial_link_unlock();
61 return NULL;
62 }
63}
64
65void* triple_buffer_begin_write_internal(uint16_t object_size, triple_buffer_object_t* object) {
66 uint8_t write_index = GET_WRITE_INDEX();
67 return object->buffer + object_size * write_index;
68}
69
70void triple_buffer_end_write_internal(triple_buffer_object_t* object) {
71 serial_link_lock();
72 uint8_t shared_index = GET_SHARED_INDEX();
73 uint8_t write_index = GET_WRITE_INDEX();
74 SET_SHARED_INDEX(write_index);
75 SET_WRITE_INDEX(shared_index);
76 SET_DATA_AVAILABLE(true);
77 serial_link_unlock();
78}
diff --git a/quantum/serial_link/protocol/triple_buffered_object.h b/quantum/serial_link/protocol/triple_buffered_object.h
new file mode 100644
index 000000000..2e57db3f5
--- /dev/null
+++ b/quantum/serial_link/protocol/triple_buffered_object.h
@@ -0,0 +1,51 @@
1/*
2The MIT License (MIT)
3
4Copyright (c) 2016 Fred Sundvik
5
6Permission is hereby granted, free of charge, to any person obtaining a copy
7of this software and associated documentation files (the "Software"), to deal
8in the Software without restriction, including without limitation the rights
9to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10copies of the Software, and to permit persons to whom the Software is
11furnished to do so, subject to the following conditions:
12
13The above copyright notice and this permission notice shall be included in all
14copies or substantial portions of the Software.
15
16THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22SOFTWARE.
23*/
24
25#ifndef SERIAL_LINK_TRIPLE_BUFFERED_OBJECT_H
26#define SERIAL_LINK_TRIPLE_BUFFERED_OBJECT_H
27
28#include <stdint.h>
29
30typedef struct {
31 uint8_t state;
32 uint8_t buffer[] __attribute__((aligned(4)));
33}triple_buffer_object_t;
34
35void triple_buffer_init(triple_buffer_object_t* object);
36
37#define triple_buffer_begin_write(object) \
38 (typeof(*object.buffer[0])*)triple_buffer_begin_write_internal(sizeof(*object.buffer[0]), (triple_buffer_object_t*)object)
39
40#define triple_buffer_end_write(object) \
41 triple_buffer_end_write_internal((triple_buffer_object_t*)object)
42
43#define triple_buffer_read(object) \
44 (typeof(*object.buffer[0])*)triple_buffer_read_internal(sizeof(*object.buffer[0]), (triple_buffer_object_t*)object)
45
46void* triple_buffer_begin_write_internal(uint16_t object_size, triple_buffer_object_t* object);
47void triple_buffer_end_write_internal(triple_buffer_object_t* object);
48void* triple_buffer_read_internal(uint16_t object_size, triple_buffer_object_t* object);
49
50
51#endif