XCP_SIM
xcp_tl.c
1 /*
2  * BlueParrot XCP
3  *
4  * (C) 2007-2022 by Christoph Schueler <github.com/Christoph2,
5  * cpu12.gems@googlemail.com>
6  *
7  * All Rights Reserved
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License along
20  * with this program; if not, write to the Free Software Foundation, Inc.,
21  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22  *
23  * s. FLOSS-EXCEPTION.txt
24  */
25 
26 #include "xcp_config.h"
27 
28 #if XCP_TRANSPORT_LAYER == XCP_ON_SXI
29 
30 #if defined(ARDUINO)
31 #include "Arduino.h"
32 #endif
33 
35 #include "xcp.h"
36 #include "xcp_tl_timeout.h"
37 #include "xcp_util.h"
40 #define XCP_SXI_MAKEWORD(buf, offs) \
41  ((*((buf) + (offs))) | ((*((buf) + (offs) + 1) << 8)))
42 
43 #define TIMEOUT_VALUE (100)
44 
45 typedef enum tagXcpTl_ReceiverStateType {
46  XCP_RCV_IDLE,
47  XCP_RCV_UNTIL_LENGTH,
48  XCP_RCV_REMAINING
49 } XcpTl_ReceiverStateType;
50 
51 typedef struct tagXcpTl_ReceiverType {
52  uint8_t Buffer[XCP_COMM_BUFLEN];
53  XcpTl_ReceiverStateType State;
54  uint16_t Index;
55  uint16_t Remaining;
56  uint16_t Dlc; /* TODO: config!!! */
57  uint16_t Ctr; /* TODO: config!!! */
59 
60 static XcpTl_ReceiverType XcpTl_Receiver;
61 
62 static void XcpTl_ResetSM(void);
63 
64 static void XcpTl_SignalTimeout(void);
65 
66 void XcpTl_Init(void) {
67  Serial.begin(115000);
68  XcpTl_ResetSM();
69  XcpTl_TimeoutInit(TIMEOUT_VALUE, XcpTl_ResetSM);
70 }
71 
72 void XcpTl_DeInit(void) {}
73 
74 void XcpTl_MainFunction(void) {
75  uint8_t octet = 0;
76 
77  if (Serial.available()) {
78  digitalWrite(LED_BUILTIN, HIGH);
79  octet = Serial.read();
80  XcpTl_FeedReceiver(octet);
81 
82  digitalWrite(LED_BUILTIN, LOW);
83  }
84  XcpTl_TimeoutCheck();
85 }
86 
95 static void XcpTl_ResetSM(void) {
96  XcpTl_Receiver.State = XCP_RCV_IDLE;
97  XcpTl_Receiver.Index = 0u;
98  XcpTl_Receiver.Dlc = 0u;
99  XcpTl_Receiver.Ctr = 0u;
100  XcpTl_Receiver.Remaining = 0u;
101 }
102 
103 void XcpTl_RxHandler(void) {}
104 
105 void XcpTl_FeedReceiver(uint8_t octet) {
106  XCP_TL_ENTER_CRITICAL();
107 
108  XcpTl_Receiver.Buffer[XcpTl_Receiver.Index] = octet;
109 
110  if (XcpTl_Receiver.State == XCP_RCV_IDLE) {
111  XcpTl_Receiver.State = XCP_RCV_UNTIL_LENGTH;
112  XcpTl_TimeoutStart();
113  } else if (XcpTl_Receiver.State == XCP_RCV_UNTIL_LENGTH) {
114  if (XcpTl_Receiver.Index == 0x01) {
115  XcpTl_Receiver.Dlc = XCP_SXI_MAKEWORD(XcpTl_Receiver.Buffer, 0x00);
116  XcpTl_Receiver.State = XCP_RCV_REMAINING;
117  XcpTl_Receiver.Remaining = XcpTl_Receiver.Dlc + 2;
118  XcpTl_TimeoutReset();
119  }
120  } else if (XcpTl_Receiver.State == XCP_RCV_REMAINING) {
121  if (XcpTl_Receiver.Index == 0x03) {
122  XcpTl_Receiver.Ctr = XCP_SXI_MAKEWORD(XcpTl_Receiver.Buffer, 0x02);
123  }
124  XcpTl_TimeoutReset();
125  XcpTl_Receiver.Remaining--;
126  if (XcpTl_Receiver.Remaining == 0u) {
127  XcpTl_ResetSM();
128  XcpTl_TimeoutStop();
129  Xcp_CtoIn.len = XcpTl_Receiver.Dlc;
130  Xcp_CtoIn.data = XcpTl_Receiver.Buffer + 4;
131  Xcp_DispatchCommand(&Xcp_CtoIn);
132  }
133  }
134  if (XcpTl_Receiver.State != XCP_RCV_IDLE) {
135  XcpTl_Receiver.Index++;
136  }
137  XCP_TL_LEAVE_CRITICAL();
138 }
139 
140 void XcpTl_Send(uint8_t const *buf, uint16_t len) {
141  XCP_TL_ENTER_CRITICAL();
142 #if defined(ARDUINO)
143  Serial.write(buf, len);
144 #endif
145 
146  XCP_TL_LEAVE_CRITICAL();
147 }
148 
149 void XcpTl_SaveConnection(void) {}
150 
151 void XcpTl_ReleaseConnection(void) {}
152 
153 void XcpTl_PrintConnectionInformation(void) {
154  printf("\nXCPonSxi\n"
155  // ; DEFAULT_PORT,
156  // Xcp_Options.tcp ? "TCP" : "UDP",
157  // Xcp_Options.ipv6 ? "IPv6" : "IPv4"
158  );
159 }
160 
161 static void XcpTl_SignalTimeout(void) {
162  XCP_TL_ENTER_CRITICAL();
163  XcpTl_ResetSM();
164  XCP_TL_LEAVE_CRITICAL();
165 }
166 
167 #if 0
168 void serialEventRun(void)
169 {
170  if (Serial.available()) {
171  serialEvent();
172  }
173 }
174 
175 void serialEvent()
176 {
177  digitalWrite(LED_BUILTIN, HIGH);
178  XcpTl_RxHandler();
179  digitalWrite(LED_BUILTIN, LOW);
180 }
181 #endif
182 
183 #endif /* XCP_TRANSPORT_LAYER == XCP_ON_SXI */