root / Version 0.9 / RS232_MUX.X / main.c @ 10dcb6e9
Historique | Voir | Annoter | Télécharger (8,117 ko)
1 | 10dcb6e9 | Enzo Niro | /*
|
---|---|---|---|
2 | * File: main.c
|
||
3 | * Author: eniro
|
||
4 | *
|
||
5 | * Created on March 25, 2024, 3:51 PM
|
||
6 | */
|
||
7 | |||
8 | #define F_CPU 24000000UL |
||
9 | |||
10 | #include <xc.h> |
||
11 | #include <math.h> |
||
12 | #include <stdlib.h> |
||
13 | #include <util/delay.h> |
||
14 | #include <avr/interrupt.h> |
||
15 | #include <avr/eeprom.h> |
||
16 | |||
17 | #include "hardware_uart.h" |
||
18 | #include "hardware_timer.h" |
||
19 | #include "frame_definitions.h" |
||
20 | |||
21 | //USART setup
|
||
22 | |||
23 | //To calculate BAUD value register -> BAUD = 64*FCLK/(16*FBAUDS)
|
||
24 | #define UART_BAUD_VALUE 833 // 10000 is equivalent as 9600 bauds according to datasheet |
||
25 | #define USART0_REG 0x3 |
||
26 | #define BOOT_MSG "RS232-MUX\r\n" |
||
27 | |||
28 | |||
29 | |||
30 | //OSC. setup
|
||
31 | #define FREQSEL 0x9 |
||
32 | #define _FREQSEL_REG_WR ((FREQSEL) << 2) |
||
33 | #define _USART0_REG_WR (USART0_REG & 0x7) |
||
34 | |||
35 | |||
36 | |||
37 | |||
38 | //////////////////////////////////////////////////////////////
|
||
39 | //Prototypes
|
||
40 | |||
41 | void bootSequence(void); |
||
42 | |||
43 | //reset watchdog counter
|
||
44 | #define WATCHDOG_RESET asm("WDR") |
||
45 | |||
46 | uint8_t global_debugBuffer[256];
|
||
47 | uint8_t global_n = 0;
|
||
48 | |||
49 | |||
50 | int main(void) { |
||
51 | |||
52 | |||
53 | |||
54 | ////////////////////////////////////////////////////////////
|
||
55 | //Local variables
|
||
56 | |||
57 | const char *boot_msg = BOOT_MSG; |
||
58 | |||
59 | cfgPort cfgVCOM1, cfgVCOM2, cfgVCOM3, cfgVCOM4; |
||
60 | uint8_t ledsCfg; |
||
61 | |||
62 | |||
63 | |||
64 | //Output buffer
|
||
65 | uint8_t MCOMBuf[256], VCOM1Buf[256], VCOM2Buf[256], VCOM3Buf[256], VCOM4Buf[256]; |
||
66 | //Output buffer index
|
||
67 | uint8_t MCOMIndex = 0, VCOM1Index = 0, VCOM2Index = 0, VCOM3Index = 0, VCOM4Index = 0; |
||
68 | //local timer counter for local process (blink led, ect...)
|
||
69 | uint32_t timerCnt = 0;
|
||
70 | //local timer for counting how many cycles passed since we've got activity on serial port ?
|
||
71 | uint32_t serialTimer = 0;
|
||
72 | |||
73 | //Counter to make a timeout if all data has passed
|
||
74 | uint8_t MCOM_counter = 0;
|
||
75 | uint8_t VCOM1_counter = 0;
|
||
76 | uint8_t VCOM2_counter = 0;
|
||
77 | uint8_t VCOM3_counter = 0;
|
||
78 | uint8_t VCOM4_counter = 0;
|
||
79 | |||
80 | |||
81 | for(int i = 0; i < 256; i++) |
||
82 | { |
||
83 | MCOMBuf[i] = 0;
|
||
84 | VCOM1Buf[i] = 0;
|
||
85 | VCOM2Buf[i] = 0;
|
||
86 | VCOM3Buf[i] = 0;
|
||
87 | VCOM4Buf[i] = 0;
|
||
88 | } |
||
89 | |||
90 | |||
91 | PORTD.DIR = 0x01; // DEBUG LED |
||
92 | //PORTMUX.USARTROUTEA = _USART0_REG_WR; //set TX and RX on PD4 and PD5 pins
|
||
93 | _PROTECTED_WRITE(CLKCTRL.OSCHFCTRLA, _FREQSEL_REG_WR); //switch to 24 MHz
|
||
94 | |||
95 | ///////////////////////////////////////////
|
||
96 | //Prepare VCOM configuration
|
||
97 | |||
98 | //At first read EEPROM !
|
||
99 | getEEPROMCfg(); //Get serial port configuration
|
||
100 | ledsCfg = getDebugLedsConfiguration(); //get debug leds configuration
|
||
101 | |||
102 | //And then, read configuration for each port...
|
||
103 | |||
104 | readConfiguration(&cfgVCOM1, 0);
|
||
105 | readConfiguration(&cfgVCOM2, 1);
|
||
106 | readConfiguration(&cfgVCOM3, 2);
|
||
107 | readConfiguration(&cfgVCOM4, 3);
|
||
108 | |||
109 | ///////////////////////////////////////////
|
||
110 | //Interrupt & serial port setup
|
||
111 | |||
112 | //Set port with debug leds
|
||
113 | initPort0(UART_BAUD_VALUE, (ledsCfg & 0x1), F8BIT_MODE, ONE_STOPBIT, NO_PARITY); //init master port with debug leds |
||
114 | initPort1(cfgVCOM1.baud, (ledsCfg & 0x2) >> 1, cfgVCOM1.dataByte, cfgVCOM1.stopBit, cfgVCOM1.parity); //init vcom1 port with debug leds |
||
115 | initPort2(cfgVCOM2.baud, (ledsCfg & 0x4) >> 2, cfgVCOM2.dataByte, cfgVCOM2.stopBit, cfgVCOM2.parity); //init vcom2 port with debug leds |
||
116 | initPort3(cfgVCOM3.baud, (ledsCfg & 0x8) >> 3, cfgVCOM3.dataByte, cfgVCOM3.stopBit, cfgVCOM3.parity); //init vcom3 port with debug leds |
||
117 | initPort4(cfgVCOM4.baud, (ledsCfg & 0x16) >> 4, cfgVCOM4.dataByte, cfgVCOM4.stopBit, cfgVCOM4.parity); //init vcom4 port with debug leds |
||
118 | //Timer init
|
||
119 | //Setup for interrupt every 25ms
|
||
120 | timerInterruptInit(0x2EE0);
|
||
121 | |||
122 | sei(); //never forget to enable global interrupt mask !
|
||
123 | |||
124 | ///////////////////////////////////////////
|
||
125 | |||
126 | //Debug led on boot sequence
|
||
127 | WATCHDOG_RESET; //reset WD counter
|
||
128 | bootSequence(); //Launch leds sequence
|
||
129 | |||
130 | |||
131 | for(uint8_t i = 0; i < 11; i++) |
||
132 | { |
||
133 | txWrite0(boot_msg[i]); |
||
134 | } |
||
135 | |||
136 | while(1) |
||
137 | { |
||
138 | WATCHDOG_RESET; //Always call this to prevent undesired boot...
|
||
139 | |||
140 | //if(portAvailable0() > 0) //check if we have bytes to read
|
||
141 | if(portAvailable0() > 0) |
||
142 | { |
||
143 | MCOMBuf[MCOMIndex] = rxRead0(); //store byte into buffer
|
||
144 | MCOMIndex++; //increment to next byte
|
||
145 | MCOM_counter = 0; //refresh timeout counter |
||
146 | } |
||
147 | |||
148 | if(portAvailable1() > 0) //check if we have bytes to read |
||
149 | { |
||
150 | VCOM1Buf[VCOM1Index] = rxRead1(); //store byte into buffer
|
||
151 | VCOM1Index++; //increment to next byte
|
||
152 | VCOM1_counter = 0; //refresh timeout counter |
||
153 | } |
||
154 | |||
155 | if(portAvailable2() > 0) //check if we have bytes to read |
||
156 | { |
||
157 | VCOM2Buf[VCOM2Index] = rxRead2(); //store byte into buffer
|
||
158 | VCOM2Index++; //increment to next byte
|
||
159 | VCOM2_counter = 0; //refresh timeout counter |
||
160 | } |
||
161 | |||
162 | if(portAvailable3() > 0) //check if we have bytes to read |
||
163 | { |
||
164 | VCOM3Buf[VCOM3Index] = rxRead3(); //store byte into buffer
|
||
165 | VCOM3Index++; //increment to next byte
|
||
166 | VCOM3_counter = 0; //refresh timeout counter |
||
167 | } |
||
168 | |||
169 | if(portAvailable4() > 0) //check if we have bytes to read |
||
170 | { |
||
171 | VCOM4Buf[VCOM4Index] = rxRead4(); //store byte into buffer
|
||
172 | VCOM4Index++; //increment to next byte
|
||
173 | VCOM4_counter = 0; //refresh timeout counter |
||
174 | } |
||
175 | |||
176 | |||
177 | //if timeout
|
||
178 | if(MCOM_counter > 10) |
||
179 | { |
||
180 | MCOM_sendframe(MCOMBuf, MCOMIndex); |
||
181 | //Clear the buffer
|
||
182 | for(uint8_t i = 0; i < MCOMIndex; i++) |
||
183 | { |
||
184 | MCOMBuf[i] = 0;
|
||
185 | } |
||
186 | MCOMIndex = 0;
|
||
187 | MCOM_counter = 0;
|
||
188 | } |
||
189 | |||
190 | |||
191 | //NOTE : Not sure that stuff will be useful...
|
||
192 | //Just in case if bytes does not match, clear counter
|
||
193 | if(MCOMIndex >= 255) |
||
194 | MCOMIndex = 0;
|
||
195 | |||
196 | if(VCOM1Index >= 255) |
||
197 | VCOM1Index = 0;
|
||
198 | |||
199 | if(VCOM2Index >= 255) |
||
200 | VCOM2Index = 0;
|
||
201 | |||
202 | if(VCOM3Index >= 255) |
||
203 | VCOM3Index = 0;
|
||
204 | |||
205 | if(VCOM4Index >= 255) |
||
206 | VCOM4Index = 0;
|
||
207 | |||
208 | |||
209 | //Refresh led status
|
||
210 | if(abs(getTimerCounts() - timerCnt) >= 25) |
||
211 | { |
||
212 | senseDebugLeds(); |
||
213 | timerCnt = getTimerCounts(); |
||
214 | } |
||
215 | |||
216 | //count
|
||
217 | if(abs(getTimerCounts() - serialTimer) >= 1) |
||
218 | { |
||
219 | //prevent incrementing counter if no bytes available...
|
||
220 | if(MCOMIndex > 0) |
||
221 | MCOM_counter++; |
||
222 | |||
223 | VCOM1_counter++; |
||
224 | VCOM2_counter++; |
||
225 | VCOM3_counter++; |
||
226 | VCOM4_counter++; |
||
227 | serialTimer = getTimerCounts(); |
||
228 | } |
||
229 | |||
230 | } |
||
231 | |||
232 | |||
233 | |||
234 | |||
235 | return 0; |
||
236 | } |
||
237 | |||
238 | |||
239 | |||
240 | |||
241 | ///////////////////////////////////////////////////////////
|
||
242 | //Functions / macros
|
||
243 | |||
244 | //Send a frame from master port that calculate whose port to send ?
|
||
245 | void MCOM_sendframe(uint8_t *data, uint8_t n)
|
||
246 | { |
||
247 | uint16_t addrFunctions[] = {&txWrite1, &txWrite2, &txWrite3, &txWrite4 }; //list of available functions addresses
|
||
248 | void (*localTxWrite)(); //function pointer |
||
249 | |||
250 | global_n = n; |
||
251 | |||
252 | //To read buffer with debugger
|
||
253 | for(int i = 0; i < 256; i++) |
||
254 | global_debugBuffer[i] = data[i]; |
||
255 | |||
256 | if(global_n == 0x02) |
||
257 | { |
||
258 | asm("nop"); |
||
259 | } |
||
260 | if(global_debugBuffer[1] == 0x03) |
||
261 | { |
||
262 | asm("nop"); |
||
263 | } |
||
264 | //At first, check if first byte is the start of text
|
||
265 | if(data[0] == STX) |
||
266 | { |
||
267 | if(data[2] == FRAME_ADDR_1 && data[3] == FRAME_ADDR_2) //check if we have the MUX address identifier |
||
268 | { |
||
269 | if(data[n-1] == CR_CHAR) //check the end of text (second byte) |
||
270 | { |
||
271 | if(data[n-2] == LF_CHAR) //check the end of text (first byte) |
||
272 | { |
||
273 | localTxWrite = addrFunctions[(data[1] < 3) ? data[1] : 3 ]; //data[3] |
||
274 | for(int i = 4; i < n-2; i++) //send frame without (STX + FRAME_ADDR_B1 + FRAME_ADDR_B2 + LF_CHAR + CR_CHAR) |
||
275 | { |
||
276 | localTxWrite(data[i]); |
||
277 | } |
||
278 | |||
279 | } |
||
280 | } |
||
281 | } |
||
282 | } |
||
283 | } |
||
284 | |||
285 | |||
286 | |||
287 | void bootSequence(void) |
||
288 | { |
||
289 | debugLedsTest(); |
||
290 | } |
||
291 | |||
292 | |||
293 | |||
294 | |||
295 | |||
296 | |||
297 | |||
298 |