3          Copyright (C) Dean Camera, 2010. 
   5   dean [at] fourwalledcubicle [dot] com 
   6           www.fourwalledcubicle.com 
  10   Copyright 2010  David Prentice (david.prentice [at] farming [dot] uk) 
  11   Copyright 2010  Peter Danneger 
  12   Copyright 2010  Dean Camera (dean [at] fourwalledcubicle [dot] com) 
  14   Permission to use, copy, modify, distribute, and sell this  
  15   software and its documentation for any purpose is hereby granted 
  16   without fee, provided that the above copyright notice appear in  
  17   all copies and that both that the copyright notice and this 
  18   permission notice and warranty disclaimer appear in supporting  
  19   documentation, and that the name of the author not be used in  
  20   advertising or publicity pertaining to distribution of the  
  21   software without specific, written prior permission. 
  23   The author disclaim all warranties with regard to this 
  24   software, including all implied warranties of merchantability 
  25   and fitness.  In no event shall the author be liable for any 
  26   special, indirect or consequential damages or any damages 
  27   whatsoever resulting from loss of use, data or profits, whether 
  28   in an action of contract, negligence or other tortious action, 
  29   arising out of or in connection with the use or performance of 
  35 volatile uint8_t srx_done
, stx_count
; 
  36 volatile uint8_t srx_data
, srx_mask
, srx_tmp
, stx_data
; 
  38 unsigned char SoftUART_IsReady(void) 
  43 unsigned char SoftUART_TxByte(unsigned char c
) 
  53 unsigned char SoftUART_IsReceived(void) 
  58 unsigned char SoftUART_RxByte(void) 
  67 void SoftUART_Init(void) 
  69         OCR2B  
= TCNT2 
+ 1;                                             // force first compare 
  70         TCCR2A 
= (1 << COM2B1
) | (1 << COM2B0
); // T1 mode 0 
  71         TCCR2B 
= (1 << FOC2B
)  | (1 << CS21
);   // CLK/8, T1 mode 0 
  72         TIMSK2 
= (1 << OCIE2B
);                                 // enable tx and wait for start 
  73         EICRA  
= (1 << ISC01
);                                  // -ve edge 
  74         EIMSK  
= (1 << INT0
);                                   // enable INT0 interrupt 
  76         stx_count 
= 0;                                                  // nothing to send 
  77         srx_done 
= 0;                                                   // nothing received 
  78         STXPORT 
|= 1 << STX
;                                    // TX output 
  79         STXDDR  
|= 1 << STX
;                                    // TX output 
  80         SRXPORT 
|= (1 << SRX
);                                  // pullup on INT0 
  83 /* ISR to detect the start of a bit being sent from the transmitter. */ 
  86         OCR2A 
= TCNT2 
+ (BIT_TIME 
/ 8 * 3 / 2); // scan 1.5 bits after start 
  88         srx_tmp 
= 0;                                                    // clear bit storage 
  89         srx_mask 
= 1;                                                   // bit mask 
  91         TIFR2 
= (1 << OCF2A
);                                   // clear pending interrupt 
  93         if (!(SRXPIN 
& (1 << SRX
)))                             // still low 
  95                 TIMSK2 
= (1 << OCIE2A
) | (1 << OCIE2B
); // wait for first bit 
  96                 EIMSK 
&= ~(1 << INT0
); 
 100 /* ISR to manage the reception of bits to the transmitter. */ 
 101 ISR(TIMER2_COMPA_vect
) 
 105                 if (SRXPIN 
& (1 << SRX
)) 
 110                 OCR2A 
+= BIT_TIME 
/ 8;                          // next bit slice 
 114                 srx_done  
= 1;                                          // mark rx data valid 
 115                 srx_data  
= srx_tmp
;                            // store rx data 
 116                 TIMSK2    
= (1 << OCIE2B
);                      // enable tx and wait for start 
 117                 EIMSK    
|= (1 << INT0
);                        // enable START irq 
 118                 EIFR      
= (1 << INTF0
);                       // clear any pending 
 122 /* ISR to manage the transmission of bits to the receiver. */ 
 123 ISR(TIMER2_COMPB_vect
) 
 125         OCR2B 
+= BIT_TIME 
/ 8;                                  // next bit slice 
 129                 if (--stx_count 
!= 9)                           // no start bit 
 131                         if (!(stx_data 
& 1))                    // test inverted data 
 132                           TCCR2A 
= (1 << COM2B1
) | (1 << COM2B0
); 
 134                           TCCR2A 
= (1 << COM2B1
); 
 136                         stx_data 
>>= 1;                                 // shift zero in from left 
 140                         TCCR2A 
= (1 << COM2B1
);                 // START bit