16FXlib
can4.c
1 //*****************************************************************************
2 // Author : Nicolas Weber
3 // Created : 29.04.2010
4 // Target MCU : Fujitsu MB96300 series
5 //
6 // This program is free software: you can redistribute it and/or modify
7 // it under the terms of the GNU General Public License as published by
8 // the Free Software Foundation, either version 3 of the License, or
9 // (at your option) any later version.
10 //
11 // This program is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
15 //
16 // You should have received a copy of the GNU General Public License
17 // along with this program. If not, see <http://www.gnu.org/licenses/>.
18 //
19 //*****************************************************************************
20 
21 #ifndef CAN4_C_
22 #define CAN4_C_
23 #include "can3.h"
24 #include "can4.h"
25 #include "can4.cfg.h"
26 #include "../util.h"
27 
28 #define CAN4_EXTRACT_NUMBER(id) (uint8_t) ((id & 0x0000F800) >> 11)
29 #define CAN4_EXTRACT_COUNT(id) (uint8_t) ((id & 0x000007C0) >> 6)
30 
31 #define _PV(x) ((uint16_t)x) << 1
32 #define _NV(x) ((uint16_t)x) << 11
33 #define _CV(x) ((uint16_t)x) << 6
34 
35 #define CAN4_RETURN_UBOUNDS(x,max,out) if(x > max) return out
36 
37 #define CAN4_BUF_MSG_UNUSED 0xFF
38 #define CAN4_BUF_UNUSED 0xFF
39 #define CAN4_BUF_EOM 0xEE
40 
41 //#define CAN4_EXTRACT_PORT(msg) (msg & 0x0000001F)
42 //#define CAN4_EXTRACT_SOURCE(msg) ((msg & 0x000007E0) >> 5)
43 //#define CAN4_EXTRACT_DATABUFFER(msg) ((msg & 0xFFFFF800) >> 11)
44 
45 //#define CAN4_PUT_PORT(port) ((uint32_t)port)
46 //#define CAN4_PUT_SOURCE(src) ((uint32_t)src) << 5
47 //#define CAN4_PUT_DATABUFFER(buf) ((uint32_t)buf) << 11
48 
49 uint8_t can4_ports[32];
50 uint8_t can4_msgbuffer[CAN4_BUF_MSG_COUNT][3]; //0 = Source, 1 = Port, 2 = Databuffer
51 uint8_t can4_databuffer[CAN4_BUF_DATA_COUNT];
52 uint8_t can4_bytebuffer[CAN4_BUF_DATA_COUNT][8];
53 
54 
55 static void can4_adaptRef(uint8_t dbuf, uint8_t databuf);
56 static uint8_t can4_getFreeMsgBuffer(void);
57 static uint8_t can4_getMsgBuffer(uint8_t port, uint8_t source);
58 static uint8_t can4_getFreeDataBuffer(void);
59 static void can4_saveDataToByteBuffer(uint8_t databuf, uint8_t* data);
60 static uint8_t can4_saveCompleteData(uint8_t databuf, uint8_t* data, uint8_t offset, uint8_t len);
61 
63  uint8_t i;
64 
65  //Reset all port values
66  for(i = 0; i <= CAN4_MAX_PORT; i++)
67  can4_ports[i] = 0;
68 
69  for(i = 0; i < CAN4_BUF_MSG_COUNT; i++)
70  can4_msgbuffer[i][0] = CAN4_BUF_MSG_UNUSED;
71 
72  for(i = 0; i < CAN4_BUF_DATA_COUNT; i++)
73  can4_databuffer[i] = CAN4_BUF_UNUSED;
74 
75  return can3_init(address);
76 }
77 
79  uint8_t tmp;
80 
81  //Return 0 if port >= 32
82  CAN4_RETURN_UBOUNDS(port,CAN4_MAX_PORT,0);
83 
84  //Return 0 if port is already open
85  if(can4_ports[port]) return 0;
86 
87  tmp = can3_maskedOpen(_PV(port),0x003E);
88 
89  if(tmp == 0) return 0;
90 
91  can4_ports[port] = tmp;
92 
93  return 1;
94 }
95 
96 uint8_t can4_send(uint8_t dest, uint8_t port, uint8_t* data, uint8_t len, uint8_t interrupt) {
97  uint8_t i = 0, n = 0, m = 0;
98  uint8_t msg[8];
99  uint8_t count;
100 
101  //CALC HEADER DATA
102  count = len / 8;
103 
104  if(len % 8)
105  count += 1;
106 
107  //SEND REST OF MESSAGE
108  for(i = 0; i < len; ) {
109  while(n < 8 && i < len) {
110  msg[n] = data[i];
111  n++; i++;
112  }
113 
114  if(!can3_send(dest,_PV(port) | _NV(m) | _CV(count), msg, n, interrupt)) return 0;
115  n = 0; m++;
116  }
117 
118  return 1;
119 }
120 
122  //Init Vars
123  uint16_t _id;
124  uint8_t _count;
125  uint8_t _num;
126  uint8_t _len;
127  uint8_t _src;
128  uint8_t _data[8];
129  uint8_t msgbuf;
130  uint8_t databuf;
131 
132  //Return 0 if port >= 32
133  CAN4_RETURN_UBOUNDS(port,CAN4_MAX_PORT,0);
134 
135  //Return 0 if port is not open
136  if(!can4_ports[port]) return 0;
137 
138  //Get MSG
139  _len = can3_getData(can4_ports[port],_data,&_src,&_id);
140 
141  if(_len == 0) return 0; //Nothing to do
142 
143  //Get MSG header
144  _count = CAN4_EXTRACT_COUNT(_id);
145  _num = CAN4_EXTRACT_NUMBER(_id);
146 
147  //single message
148  if(_count == 1) {
149  uint8_t i;
150  for(i = 0; i < _len; i++)
151  data[i] = _data[i];
152 
153  *src = _src;
154  return _len;
155  }
156 
157  /*
158  * Multiple Messages
159  */
160 
161  //get free msgbuffer
162  msgbuf = ((_num == 0) ? can4_getFreeMsgBuffer() : can4_getMsgBuffer(port,_src));
163  if(msgbuf == 0) return 0; //Msgbuffer overflow
164 
165  //get free databuffer
166  databuf = can4_getFreeDataBuffer();
167  if(databuf == 0) return 0; //Databuffer overflow
168 
169  //index correction
170  msgbuf--;
171  databuf--;
172 
173  //save msg data
174  can4_databuffer[databuf] = CAN4_BUF_EOM;
175  can4_saveDataToByteBuffer(databuf, _data);
176 
177  if(_num == 0) { //save msg header
178  //can4_msgbuffer[msgbuf] = CAN4_PUT_PORT(port) | CAN4_PUT_SOURCE(_src) | CAN4_PUT_DATABUFFER(databuf);
179  can4_msgbuffer[msgbuf][0] = _src;
180  can4_msgbuffer[msgbuf][1] = port;
181  can4_msgbuffer[msgbuf][2] = databuf;
182  return 0;
183  }
184 
185  //adapt reference
186  can4_adaptRef(can4_msgbuffer[msgbuf][2],databuf);
187 
188  //check if msg is complete
189  if(_num == (_count - 1)) { //msg complete
190  *src = _src;
191  _len = can4_saveCompleteData(can4_msgbuffer[msgbuf][2],data, 0,0);
192 
193  //free space
194  can4_msgbuffer[msgbuf][0] = CAN4_BUF_MSG_UNUSED;
195 
196  return _len;
197  }
198 
199  //sry still not complete
200  return 0;
201 }
202 
203 static uint8_t can4_saveCompleteData(uint8_t databuf, uint8_t* data, uint8_t offset, uint8_t len) {
204  uint8_t i;
205  uint8_t _len;
206 
207  for(i = 0; i < 8; i++) {
208  data[offset * 8 + i] = can4_bytebuffer[databuf][i];
209  }
210 
211  if(can4_databuffer[databuf] != CAN4_BUF_EOM)
212  _len = can4_saveCompleteData(can4_databuffer[databuf], data, offset + 1, len + 8);
213  else
214  _len = (len + 8);
215 
216  //free space
217  can4_databuffer[databuf] = CAN4_BUF_UNUSED;
218  return _len;
219 }
220 
221 static void can4_adaptRef(uint8_t dbuf, uint8_t databuf) {
222  if(can4_databuffer[dbuf] == CAN4_BUF_EOM)
223  can4_databuffer[dbuf] = databuf;
224  else
225  can4_adaptRef(can4_databuffer[dbuf],databuf);
226 }
227 
228 static uint8_t can4_getMsgBuffer(uint8_t port, uint8_t source) {
229  uint8_t i;
230 
231  for(i = 1; i <= CAN4_BUF_MSG_COUNT; i++) {
232  if(can4_msgbuffer[i - 1][0] == source &&
233  can4_msgbuffer[i - 1][1] == port) {
234  return i;
235  }
236  }
237 
238  return 0;
239 }
240 
241 static uint8_t can4_getFreeMsgBuffer(void) {
242  uint8_t i;
243  for(i = 1; i <= CAN4_BUF_MSG_COUNT; i++) {
244  if(can4_msgbuffer[i-1][0] == CAN4_BUF_MSG_UNUSED) {
245  return i;
246  }
247  }
248 
249  return 0;
250 }
251 
252 static uint8_t can4_getFreeDataBuffer(void) {
253  uint8_t i;
254  for(i = 1; i <= CAN4_BUF_DATA_COUNT; i++) {
255  if(can4_databuffer[i-1] == CAN4_BUF_UNUSED) {
256  return i;
257  }
258  }
259 
260  return 0;
261 }
262 
263 static void can4_saveDataToByteBuffer(uint8_t databuf, uint8_t* data) {
264  uint8_t i;
265 
266  for(i = 0; i < 8; i++)
267  can4_bytebuffer[databuf][i] = data[i];
268 }
269 
270 void can4_close(uint8_t port) {
271  if(can4_ports[port]) {
272  can3_close(can4_ports[port]);
273  can4_ports[port] = 0;
274  }
275 }
276 
277 #endif /* CAN4_C_ */
uint8_t can3_maskedOpen(uint16_t uid, uint16_t idMask)
Definition: can3.c:197
uint8_t can4_getData(uint8_t port, uint8_t *data, uint8_t *src)
Definition: can4.c:121
uint8_t can4_open(uint8_t port)
Definition: can4.c:78
uint8_t can3_getData(uint8_t buffer, uint8_t *data, uint8_t *source, uint16_t *id)
Definition: can3.c:225
unsigned int uint16_t
Definition: inttypes.h:50
unsigned char uint8_t
Definition: inttypes.h:35
uint8_t can4_send(uint8_t dest, uint8_t port, uint8_t *data, uint8_t len, uint8_t interrupt)
Definition: can4.c:96
uint8_t can3_init(uint8_t address)
Definition: can3.c:120
uint8_t can3_send(uint8_t dest, uint16_t uid, uint8_t *data, uint8_t len, uint8_t interrupt)
Definition: can3.c:150
void can3_close(uint8_t buffer)
Definition: can3.c:257
void can4_close(uint8_t port)
Definition: can4.c:270
uint8_t can4_init(uint8_t address)
Definition: can4.c:62