2 #include "oXs_out_multiplex.h"
3 #if defined(PROTOCOL) && (PROTOCOL == MULTIPLEX)
6 // ************************* Several parameters to help debugging
7 //#define DEBUGSETNEWDATA
8 //#define DEBUGFORMATONEVALUE
10 //#define DEBUG_MULTIPLEX_WITHOUT_RX // this allows to let oXs generates dummy data when there is no Rx to give the polling on the bus. In this case, oXs does not look at the pooling to send data
11 //#define DEBUG_FORCE_VSPEED_TO 123 // this is used to force oXs to send a fixed dummy value for Vspeed in order to test if an issue result of bmp180 or from Multiplex protocol.
13 extern unsigned long micros( void ) ;
14 extern unsigned long millis( void ) ;
15 extern void delay(unsigned long ms
) ;
17 struct t_mbAllData multiplexData
;
18 volatile uint8_t sendStatus
;
19 int fieldContainsData
[][7] = { SETUP_MULTIPLEX_DATA_TO_SEND
} ; // contains the set up of field to be transmitted, the first field contains the Multiplex adress to be used for this measurement
20 int numberOfFields
= sizeof(fieldContainsData
) / sizeof(fieldContainsData
[0]) ;
21 uint8_t multiplexUnit
[] = { MULTIPLEX_UNITS
} ; // contains the unit code (4 bits) for each OXS measurement
24 OXS_OUT::OXS_OUT(uint8_t pinTx
,HardwareSerial
&print
)
26 OXS_OUT::OXS_OUT(uint8_t pinTx
)
31 printer
= &print
; //operate on the address of print
36 // **************** Setup the OutputLib *********************
37 void OXS_OUT::setup() {
40 TRXDDR
&= ~( 1 << PIN_SERIALTX
) ; // PIN is input, tri-stated.
41 TRXPORT
&= ~( 1 << PIN_SERIALTX
) ; // PIN is input, tri-stated.
43 // Activate pin change interupt on Tx pin
45 PCMSK2
|= 0x10 ; // IO4 (PD4) on Arduini mini
46 #elif PIN_SERIALTX == 2
47 PCMSK2
|= 0x04 ; // IO2 (PD2) on Arduini mini
49 #error "This PIN is not supported"
52 PCIFR
= (1<<PCIF2
) ; // clear pending interrupt
54 //initMultiplexUart( &sportData ) ;
55 initMultiplexUart( &multiplexData
) ;
58 printer
->print(F("Multiplex Output Module: TX Pin="));
59 printer
->println(_pinTx
);
60 printer
->print(F(" milli="));
61 printer
->println(millis());
62 printer
->println(F("Multiplex Output Module: Setup!"));
63 printer
->print(F("Number of fields to send = "));
64 printer
->println(numberOfFields
);
65 for (int rowNr
= 0 ; rowNr
< numberOfFields
; rowNr
++) {
66 printer
->print(fieldContainsData
[rowNr
][0],HEX
); printer
->print(F(" , "));
67 printer
->print(fieldContainsData
[rowNr
][1]); printer
->print(F(" , "));
68 printer
->print(fieldContainsData
[rowNr
][2]); printer
->print(F(" , "));
69 printer
->print(fieldContainsData
[rowNr
][3]); printer
->print(F(" , "));
70 printer
->println(fieldContainsData
[rowNr
][4]);
73 for ( int mbIndex
= 0 ; mbIndex
<= MB_MAX_ADRESS
; mbIndex
++ ) {
74 multiplexData
.mbData
[mbIndex
].response
[0] = mbIndex
;
75 multiplexData
.mbData
[mbIndex
].active
= NOT_ACTIVE
;
77 for ( int mbIndex
= 0 ; mbIndex
< numberOfFields
; mbIndex
++ ) {
78 multiplexData
.mbData
[fieldContainsData
[mbIndex
][0]].response
[0] = ( fieldContainsData
[mbIndex
][0] << 4) | ( multiplexUnit
[ fieldContainsData
[mbIndex
][1] ] );
79 multiplexData
.mbData
[fieldContainsData
[mbIndex
][0]].response
[1] = (uint8_t) MB_NOVALUE
; // low byte
80 multiplexData
.mbData
[fieldContainsData
[mbIndex
][0]].response
[2] = MB_NOVALUE
>> 8 ; // hight byte
81 multiplexData
.mbData
[fieldContainsData
[mbIndex
][0]].active
= AVAILABLE
;
84 // for debug purpose only
85 multiplexData
.mbData
[15].response
[0] = 0xF0 ;
86 multiplexData
.mbData
[15].response
[1] = 0x0F ;
87 multiplexData
.mbData
[15].response
[2] = 0xAA ;
89 for ( int mbIndex
= 0 ; mbIndex
<= MB_MAX_ADRESS
; mbIndex
++ ) {
91 Serial
.print( mbIndex
);
92 Serial
.print(" Act=");
93 Serial
.print( multiplexData
.mbData
[mbIndex
].active
, HEX
);
95 Serial
.print( multiplexData
.mbData
[mbIndex
].response
[0], HEX
);
97 Serial
.print( multiplexData
.mbData
[mbIndex
].response
[1], HEX
);
99 Serial
.println( multiplexData
.mbData
[mbIndex
].response
[2], HEX
);
108 void OXS_OUT::sendData()
110 for ( uint8_t mbIndex
= 0 ; mbIndex
< numberOfFields
; mbIndex
++ ) {
111 formatOneValue( mbIndex
) ;
115 //*************************************
116 // Format the sensor data into an array containing the 3 bytes to sent
117 // process occurs only if measurement has been flagged as available by the sensor
118 // return 0 if data has been processed; return the internal code of the measurement otherwise
119 //************************************
120 uint8_t OXS_OUT::formatOneValue( uint8_t currentFieldToSend
) {
121 static int32_t valueTemp
;
122 static uint8_t alarm
;
128 uint8_t GPS_no_fix
= ( (GPS_fix_type
!= 3 ) && (GPS_fix_type
!= 4 ) ) ; // this flag is true when there is no fix
131 switch ( fieldContainsData
[currentFieldToSend
][1] ) {
134 if ( ! varioData
->absoluteAlt
.available
) return 0 ;
135 valueTemp
= (varioData
->absoluteAlt
.value
) / 100 ;
136 varioData
->absoluteAlt
.available
= false ;
137 #ifdef DEBUGFORMATONEVALUE
139 Serial
.print( millis());
141 Serial
.print( currentFieldToSend
);
142 Serial
.println("Alt available ");
145 case VERTICAL_SPEED
:
146 if ( ! mainVspeed
.available
) return 0;
147 valueTemp
= mainVspeed
.value
/ 10 ;
148 mainVspeed
.available
= false ;
149 #ifdef DEBUG_FORCE_VSPEED_TO
150 valueTemp
= DEBUG_FORCE_VSPEED_TO
;
154 if ( !varioData
->sensitivity
.available
) return 0;
155 valueTemp
= varioData
->sensitivity
.value
;
156 varioData
->sensitivity
.available
= false ;
158 // case ALT_OVER_10_SEC :
159 // if ( ! varioData->vSpeed10SecAvailable ) return 0;
160 // valueTemp = varioData->vSpeed10Sec / 100 ; // todo : adjust decimals
161 // varioData->vSpeed10SecAvailable = false ;
164 if ( ! varioData
->relativeAlt
.available
) return 0 ;
165 valueTemp
= (varioData
->relativeAlt
.value
) / 100 ;
166 varioData
->relativeAlt
.available
= false ;
169 if ( ! varioData
->relativeAltMaxAvailable
) return 0 ;
170 valueTemp
= (varioData
->relativeAltMax
) / 100 ;
171 varioData
->relativeAltMaxAvailable
= false ;
179 if ( ! varioData_2->absoluteAltAvailable ) return 0;
180 valueTemp = varioData_2->absoluteAlt / 100 ;
181 varioData_2->absoluteAltAvailable = false ;
183 case VERTICAL_SPEED_2 :
184 if ( ! varioData_2->climbRateAvailable ) return 0;
185 valueTemp = varioData_2->climbRate / 10 ;
186 varioData_2->climbRateAvailable = false ;
189 if ( ! varioData_2->sensitivityAvailable ) return 0;
190 valueTemp = varioData_2->sensitivity ;
191 varioData_2->sensitivityAvailable = false ;
193 case ALT_OVER_10_SEC_2 :
194 if ( ! varioData_2->vSpeed10SecAvailable ) return 0;
195 valueTemp = varioData_2->vSpeed10Sec / 100 ; // todo : adjust decimals
196 varioData_2->vSpeed10SecAvailable = false ;
198 case REL_ALTIMETER_2 :
199 if ( ! varioData_2->relativeAltAvailable ) return 0 ;
200 valueTemp = (varioData_2->relativeAlt ) / 100 ;
201 varioData_2->relativeAltAvailable = false ;
206 #if defined (VARIO ) && defined (VARIO2)
207 case VERTICAL_SPEED_A :
208 if ( ! averageVSpeedAvailable ) return 0;
209 valueTemp = averageVSpeed / 10 ;
210 averageVSpeedAvailable = false ;
214 #if defined (VARIO ) && ( defined (VARIO2) || defined( AIRSPEED) || defined( USE_6050) ) && defined (VARIO_PRIMARY ) && defined (VARIO_SECONDARY ) && defined (PIN_PPM)
216 if ( ! switchVSpeedAvailable ) return 0;
217 valueTemp = switchVSpeed / 10 ;
218 switchVSpeedAvailable = false ;
222 #ifdef AIRSPEED_IS_USED
224 if ( ! airSpeedData
->airSpeed
.available
) return 0;
225 valueTemp
= airSpeedData
->airSpeed
.value
* 1.852; // convert from 1/10 of knots to 1/10 of Km/h
226 airSpeedData
->airSpeed
.available
= false ;
228 // case PRANDTL_COMPENSATION :
229 // if ( ! airSpeedData->compensationAvailable ) return 0;
230 // valueTemp = airSpeedData->compensation / 10 ;
231 // airSpeedData->compensationAvailable = false ;
233 #endif // End airpseed
235 //#if defined (VARIO) && defined ( AIRSPEED)
236 // case PRANDTL_DTE :
237 // if ( ! compensatedClimbRateAvailable ) return 0;
238 // valueTemp = compensatedClimbRate / 10 ;
239 // compensatedClimbRateAvailable = false ;
241 //#endif // End defined (VARIO) && defined ( AIRSPEED)
243 #if defined(ARDUINO_MEASURES_VOLTAGES) && (ARDUINO_MEASURES_VOLTAGES == YES)
245 if (! voltageData
->mVolt
[0].available
) return 0;
246 valueTemp
= voltageData
->mVolt
[0].value
/ 100;
247 voltageData
->mVolt
[0].available
= false ;
250 if ( ! voltageData
->mVolt
[1].available
) return 0;
251 valueTemp
= voltageData
->mVolt
[1].value
/ 100 ;
252 voltageData
->mVolt
[1].available
= false ;
255 if ( ! voltageData
->mVolt
[2].available
) return 0;
256 valueTemp
= voltageData
->mVolt
[2].value
/ 100 ;
257 voltageData
->mVolt
[2].available
= false ;
260 if ( ! voltageData
->mVolt
[3].available
) return 0;
261 valueTemp
= voltageData
->mVolt
[3].value
/ 100 ;
262 voltageData
->mVolt
[3].available
= false ;
265 if ( ! voltageData
->mVolt
[4].available
) return 0;
266 valueTemp
= voltageData
->mVolt
[4].value
/ 100 ;
267 voltageData
->mVolt
[4].available
= false ;
270 if ( ! voltageData
->mVolt
[5].available
) return 0;
271 valueTemp
= voltageData
->mVolt
[5].value
/ 100 ;
272 voltageData
->mVolt
[5].available
= false ;
276 #if defined(ARDUINO_MEASURES_A_CURRENT) && (ARDUINO_MEASURES_A_CURRENT == YES)
278 if ( ! currentData
->milliAmps
.available
) return 0;
279 valueTemp
= currentData
->milliAmps
.value
/100;
280 currentData
->milliAmps
.available
= false ;
283 if ( ! currentData
->consumedMilliAmps
.available
) return 0;
284 valueTemp
= currentData
->consumedMilliAmps
.value
;
285 currentData
->consumedMilliAmps
.available
= false ;
289 #if defined(ARDUINO_MEASURES_VOLTAGES) && (ARDUINO_MEASURES_VOLTAGES == YES) && (NUMBEROFCELLS > 0) // This part has still to be adapted for Multiplex !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
291 if ( ! voltageData
->mVoltCell_Available
[0] ) return 0;
292 valueTemp
= voltageData
->mVoltCell
[0] /100 ;
293 voltageData
->mVoltCell_Available
[0] = false ;
296 if ( ! voltageData
->mVoltCell_Available
[1] ) return 0;
297 valueTemp
= voltageData
->mVoltCell
[1] / 100 ;
298 voltageData
->mVoltCell_Available
[1] = false ;
301 if ( ! voltageData
->mVoltCell_Available
[2] ) return 0;
302 valueTemp
= voltageData
->mVoltCell
[2] / 100 ;
303 voltageData
->mVoltCell_Available
[2] = false ;
306 if ( ! voltageData
->mVoltCell_Available
[3] ) return 0;
307 valueTemp
= voltageData
->mVoltCell
[3] / 100 ;
308 voltageData
->mVoltCell_Available
[3] = false ;
311 if ( ! voltageData
->mVoltCell_Available
[4] ) return 0;
312 valueTemp
= voltageData
->mVoltCell
[4] / 100 ;
313 voltageData
->mVoltCell_Available
[4] = false ;
316 if ( ! voltageData
->mVoltCell_Available
[5] ) return 0;
317 valueTemp
= voltageData
->mVoltCell
[5] / 100 ;
318 voltageData
->mVoltCell_Available
[5] = false ;
321 if ( ! voltageData
->mVoltCellMin_Available
) return 0;
322 valueTemp
= voltageData
->mVoltCellMin
/ 100 ;
323 voltageData
->mVoltCellMin_Available
= false ;
326 if ( ! voltageData
->mVoltCellTot_Available
) return 0;
327 valueTemp
= voltageData
->mVoltCellTot
/ 100 ;
328 voltageData
->mVoltCellTot_Available
= false ;
331 #endif // NUMBEROFCELLS > 0
335 if ( ! ppm
.available
) return 0;
336 valueTemp
= ppm
.value
;
337 ppm
.available
= false ;
344 if ( ! sport_rpm
.available
) return 0;
345 #if defined (PULSES_PER_ROTATION)
346 valueTemp
= sport_rpm
.value
* 60.0 / PULSES_PER_ROTATION
;
347 #else // if PULSES_PER_ROTATION is not defined, we assume 1
348 valueTemp
= sport_rpm
.value
* 60 ;
350 sport_rpm
.available
= false ;
354 if ( ! test1
.available
) return 0;
355 valueTemp
= test1
.value
;
356 test1
.available
= false ;
359 if ( ! test2
.available
) return 0;
360 valueTemp
= test2
.value
;
361 test2
.available
= false ;
364 if ( ! test3
.available
) return 0;
365 valueTemp
= test3
.value
;
366 test3
.available
= false ;
371 if (GPS_no_fix
) return 0 ;
372 valueTemp
= GPS_ground_course
/ 10000 ; // convert from degre * 100000 to 1/10 of degree
375 if (GPS_no_fix
) return 0 ;
377 valueTemp
= ((uint32_t) GPS_speed_3d
) * 36 /100 ; // convert from cm/sec to 1/10 of km/h
379 valueTemp
= ((uint32_t) GPS_speed_2d
) * 36 /100 ; // convert from cm/sec to 1/10 of km/h
383 if (GPS_no_fix
) return 0 ;
384 valueTemp
= GPS_altitude
/ 1000 ; // convert from mm to m
387 if (GPS_no_fix
) return 0 ;
388 valueTemp
= GPS_distance
; // keep in m
391 if (GPS_no_fix
) return 0 ;
392 valueTemp
= GPS_bearing
* 10 ; // convert from degree to 1/10 of degree
394 #endif // end GPS_INSTALLED
396 // if ( (fieldContainsData[currentFieldToSend][0] != 0) ) { ; // to be adapted in a condition that protect modification of data array while data are transfered to TX buffer array
398 valueTemp
= (valueTemp
* fieldContainsData
[currentFieldToSend
][2] / fieldContainsData
[currentFieldToSend
][3]) + fieldContainsData
[currentFieldToSend
][4] ;
399 alarm
= (( valueTemp
<= fieldContainsData
[currentFieldToSend
][5] ) || ( valueTemp
>= fieldContainsData
[currentFieldToSend
][6]) ) ? 1 : 0;
400 setMultiplexNewData( fieldContainsData
[currentFieldToSend
][0] , valueTemp
, alarm
) ;
401 return fieldContainsData
[currentFieldToSend
][1] ;
405 void OXS_OUT::setMultiplexNewData( uint16_t id
, int32_t value
, uint8_t alarm
)
407 #ifdef DEBUGSETNEWDATA
408 int32_t valueOrig
= value
;
410 multiplexData
.mbData
[id
].active
= LOCKED
;
413 multiplexData
.mbData
[id
].response
[1] = value
;
414 multiplexData
.mbData
[id
].response
[2] = value
>> 8 ;
415 multiplexData
.mbData
[id
].active
= AVAILABLE
;
416 #ifdef DEBUGSETNEWDATA
417 Serial
.print("set new data at ");
418 Serial
.print( millis());
419 Serial
.print(" for id=");
422 Serial
.print( multiplexData
.mbData
[id
].response
[0] , HEX
);
424 Serial
.print( multiplexData
.mbData
[id
].response
[1] , HEX
);
426 Serial
.print( multiplexData
.mbData
[id
].response
[2] , HEX
);
428 Serial
.print( varioData
->absoluteAlt
.value
);
430 Serial
.print( mainVspeed
.value
);
431 Serial
.print(" Vo=");
432 Serial
.print( valueOrig
);
439 //---------------------------------- Here the code to handle the UART
441 //#define DEBUGSETNEWDATA
442 //#define DEBUGASERIAL
445 #define FORCE_INDIRECT(ptr) __asm__ __volatile__ ("" : "=e" (ptr) : "0" (ptr))
447 volatile uint8_t state
; //!< Holds the state of the UART.
448 static volatile unsigned char SwUartTXData
; //!< Data to be transmitted.
449 static volatile unsigned char SwUartTXBitCount
; //!< TX bit counter.
450 static volatile uint8_t SwUartRXData
; //!< Storage for received bits.
451 static volatile uint8_t SwUartRXBitCount
; //!< RX bit counter.
452 static volatile uint8_t TxCount
;
454 volatile uint8_t debugUartRx
;
456 volatile uint8_t ppmInterrupted
; // This flag is activated at the end of handling interrupt on Timer 1 Compare A if during this interrupt handling an interrupt on pin change (INT0 or INT1) occurs
457 // in this case, ppm will be wrong and has to be discarded
460 static volatile uint8_t TxMultiplexData
[3] ; // array containing the char to transmit (is filled only when a polling address is received
461 //static uint8_t firstMultiplexData ;
462 struct t_mbAllData
* volatile ThisMultiplexData
= 0 ;
464 ISR(TIMER1_COMPA_vect
)
468 case TRANSMIT
: // startbit has been sent, it is time to output now 8 bits and 1 stop bit
472 if( SwUartTXBitCount
< 8 ) { // If not 8 bits have been sent
473 if( SwUartTXData
& 0x01 ) { // If the LSB of the TX buffer is 1:
475 } else { // Otherwise:
476 CLEAR_TX_PIN_MB() ; // Send a logic 0 on the TX_PIN
478 SwUartTXData
= SwUartTXData
>> 1 ; // Bitshift the TX buffer and
479 SwUartTXBitCount
+= 1 ; // increment TX bit counter.
480 } else { //Send stop bit.
481 SET_TX_PIN_MB() ; // Output a logic 1.
482 state
= TRANSMIT_STOP_BIT
;
484 OCR1A
+= TICKS2WAITONEMULTIPLEX
; // Count one period into the future.
490 case TRANSMIT_STOP_BIT
: //************************************* handling after the stop bit has been sent
491 if ( ++TxCount
< 3 ) { // there are 3 bytes to send in the Multiplex interface ?
492 SwUartTXData
= TxMultiplexData
[TxCount
] ;
493 // SwUartTXData = TxCount ;
494 CLEAR_TX_PIN_MB(); // Send a logic 0 on the TX_PIN as start bit
495 OCR1A
= TCNT1
+ TICKS2WAITONEMULTIPLEX
- INTERRUPT_BETWEEN_TRANSMIT
; // Count one period into the future.
496 SwUartTXBitCount
= 0 ;
498 } else { // 3 bytes have already been sent
500 // sendStatus = SEND ;
501 OCR1A
+= DELAY_2000
; // 2mS gap before listening
502 TRXDDR
&= ~( 1 << PIN_SERIALTX
) ; // PIN is input
503 TRXPORT
&= ~( 1 << PIN_SERIALTX
) ; // PIN is tri-stated.
507 case RECEIVE
: // Start bit has been received and we will read bits of data receiving, LSB first.
508 OCR1A
+= TICKS2WAITONEMULTIPLEX
; // Count one period after the falling edge is trigged.
509 uint8_t data
; // Use a temporary local storage (it saves some bytes (and perhaps time)
510 data
= SwUartRXBitCount
;
511 if( data
< 8 ) { //If 8 bits are not yet read
512 SwUartRXBitCount
= data
+ 1 ;
513 data
= SwUartRXData
;
514 data
>>= 1 ; // Shift due to receiving LSB first.
515 if( !(GET_RX_PIN( ) == 0 )) data
|= 0x80 ; // If a logical 1 is read, let the data mirror this.
516 SwUartRXData
= data
;
517 } else { //Done receiving = 8 bits are in SwUartRXData
518 struct t_mbAllData
* volatile pdata
= ThisMultiplexData
;
519 FORCE_INDIRECT( pdata
) ;
520 if ( SwUartRXData
> MB_MAX_ADRESS
) {
521 // mb_commandReceived ( SwUartRXData ) ; to implement if wanted in a second phase
523 OCR1A
+= DELAY_4000
; // 4mS gap before listening (take care that 4096 is the max we can wait because timer 1 is 16 bits and prescaler = 1)
525 if ( pdata
->mbData
[ SwUartRXData
] . active
== AVAILABLE
) {
526 TxMultiplexData
[0] = pdata
->mbData
[SwUartRXData
].response
[0] ;
527 TxMultiplexData
[1] = pdata
->mbData
[SwUartRXData
].response
[1] ;
528 TxMultiplexData
[2] = pdata
->mbData
[SwUartRXData
].response
[2] ;
529 if ( (TxMultiplexData
[2] != (MB_NOVALUE
>>8)) || (TxMultiplexData
[1] != (MB_NOVALUE
& 0xff)) ) pdata
->mbData
[ SwUartRXData
] . active
= NOT_AVAILABLE
; // this line could be set in comment if we want to send same data and not only when a new calculation is done
531 OCR1A
+= ( DELAY_1600
- TICKS2WAITONEMULTIPLEX
) ; // 1.6ms gap before sending
532 } else { // Status was not AVAILABLE, so there are no data ready to send
534 OCR1A
+= DELAY_4000
; // 4mS gap before listening (take care that 4096 is the max we can wait because timer 1 is 16 bits and prescaler = 1)
536 } // end receiving 1 byte
537 } // End receiving 1 bit or 1 byte (8 bits)
540 case TxPENDING
: //End of delay before sending data has occurs
541 CLEAR_TX_PIN_MB() ; // Send a start bit (logic 0 on the TX_PIN).
542 OCR1A
= TCNT1
+ TICKS2WAITONEMULTIPLEX
- INTERRUPT_ENTRY_TRANSMIT
; // Count one period into the future.
543 SwUartTXBitCount
= 0 ;
544 SwUartTXData
= TxMultiplexData
[0] ;
549 case WAITING
: // At the end of wait time, stop timer interrupt but allow pin change interrupt in order to allow to detect incoming data
550 state
= IDLE
; // Go back to idle.
551 DISABLE_TIMER_INTERRUPT() ; // Stop the timer interrupts.
552 CLEAR_PIN_CHANGE_INTERRUPT() ; // clear pending pin change interrupt
553 ENABLE_PIN_CHANGE_INTERRUPT() ; // pin change interrupt enabled
554 #ifdef DEBUG_MULTIPLEX_WITHOUT_RX // When no Rx is connected, oXs has to use only timer interrupts.
555 DISABLE_PIN_CHANGE_INTERRUPT() ; // pin change interrupt disabled
556 CLEAR_TIMER_INTERRUPT() ; // Clear interrupt bits
557 ENABLE_TIMER_INTERRUPT() ; // Enable timer1 interrupt on again
561 #ifdef DEBUG_MULTIPLEX_WITHOUT_RX
562 case IDLE
: // When there is no RX, there is no pin change interrupt. State is IDLE by default or after sending one set of data
563 // here we will load some dummy data to transmit, wait for 4msec and we will go to TxPending to transmit the data.
564 static uint8_t lineWhenDebugging
= 0 ;
565 struct t_mbAllData
* volatile pdataDebug
;
566 pdataDebug
= ThisMultiplexData
;
567 FORCE_INDIRECT( pdataDebug
) ;
568 lineWhenDebugging
++ ;
569 if ( lineWhenDebugging
> MB_MAX_ADRESS
) lineWhenDebugging
= 0 ;
570 if ( pdataDebug
->mbData
[ lineWhenDebugging
] . active
== AVAILABLE
) {
571 TxMultiplexData
[0] = pdataDebug
->mbData
[lineWhenDebugging
].response
[0] ;
572 TxMultiplexData
[1] = pdataDebug
->mbData
[lineWhenDebugging
].response
[1] ;
573 TxMultiplexData
[2] = pdataDebug
->mbData
[lineWhenDebugging
].response
[2] ;
574 pdataDebug
->mbData
[ lineWhenDebugging
] . active
= NOT_AVAILABLE
;
575 // TxMultiplexData[0] = 0x55 ; TxMultiplexData[1] = 0xAA ; TxMultiplexData[2] = 0x55 ; // can be use to measure the timing between bits
577 OCR1A
+= DELAY_2000
;
578 } else { // Status was not AVAILABLE, so there are no data ready to send
579 OCR1A
+= DELAY_100
; // 100usec gap before trying again that another data becomes available
586 state
= IDLE
; // Error, should not occur. Going to a safe state.
588 //#ifdef PPM_INTERRUPT
589 // if ( EIFR & PPM_INT_BIT) ppmInterrupted = 1 ;
596 //brief Function to initialize the UART for multiplex protocol
597 // This function will set up pins to transmit and receive on. Control of Timer1 and pin change interrupt 0.
598 void initMultiplexUart( struct t_mbAllData
* volatile pdata
) //*************** initialise UART for Multiplex
600 ThisMultiplexData
= pdata
; // this allows the ISR routine to get access to the data in OXS_Out_Multiplex
603 TRXDDR
&= ~( 1 << PIN_SERIALTX
) ; // PIN is input.
604 TRXPORT
&= ~( 1 << PIN_SERIALTX
) ; // PIN is tri-stated.
606 // External interrupt
608 #if PIN_SERIALTX == 4
609 PCMSK2
|= 0x10 ; // IO4 (PD4) on Arduini mini
610 #elif PIN_SERIALTX == 2
611 PCMSK2
|= 0x04 ; // IO2 (PD2) on Arduini mini
613 #error "This PIN is not supported"
615 CLEAR_PIN_CHANGE_INTERRUPT() ;
616 ENABLE_PIN_CHANGE_INTERRUPT() ;
617 state
= IDLE
; // Internal State Variable
620 DDRC
= 0x01 ; // PC0 as o/p debug = pin A0 !!!!
624 #ifdef DEBUG_MULTIPLEX_WITHOUT_RX // in this debug case, we have to enable timer interrupt without waiting for a pin change interrupt.
625 DISABLE_PIN_CHANGE_INTERRUPT() ; // pin change interrupt disabled
626 CLEAR_TIMER_INTERRUPT() ; // Clear interrupt bits
627 ENABLE_TIMER_INTERRUPT() ; // Enable timer1 interrupt on again
632 // ! \brief External interrupt service routine. ********************
633 // Interrupt on Pin Change to detect change on level on Multiplex signal (= could be a start bit)
635 // The falling edge in the beginning of the start
636 // bit will trig this interrupt. The state will
637 // be changed to RECEIVE, and the timer interrupt
638 // will be set to trig one and a half bit period
639 // from the falling edge. At that instant the
640 // code should sample the first data bit.
642 // note initMultiplexUart( void ) must be called in advance.
644 // This is the pin change interrupt for port D
645 // This assumes it is the only pin change interrupt
650 if (!( TRXPIN
& ( 1 << PIN_SERIALTX
) )) { // Pin is low = start bit
651 DISABLE_PIN_CHANGE_INTERRUPT() ; // pin change interrupt disabled
652 state
= RECEIVE
; // Change state
653 DISABLE_TIMER_INTERRUPT() ; // Disable timer to change its registers.
654 OCR1A
= TCNT1
+ TICKS2WAITONE_HALFMULTIPLEX
- INTERRUPT_EXEC_CYCL
- INTERRUPT_EARLY_BIAS
; // Count one and a half period into the future.
658 SwUartRXBitCount
= 0 ; // Clear received bit counter.
659 CLEAR_TIMER_INTERRUPT() ; // Clear interrupt bits
660 ENABLE_TIMER_INTERRUPT() ; // Enable timer1 interrupt on again
662 //#ifdef PPM_INTERRUPT
663 // if ( EIFR & PPM_INT_BIT) ppmInterrupted = 1 ;
666 } // end ISR pin change
671 // -------------------------End of Multiplex protocol--------------------------------------------------------------------------------------
673 #endif // END of MULTIPLEX