1 | /************************************************************************/
|
2 | /* */
|
3 | /* Software UART using T1 */
|
4 | /* */
|
5 | /* Author: P. Dannegger */
|
6 | /* danni@specs.de */
|
7 | /* */
|
8 | /************************************************************************/
|
9 | #include <main.h>
|
10 | #include <suart.h>
|
11 |
|
12 |
|
13 | #define BIT_TIME (u16)((XTAL + BAUD/2) / BAUD)
|
14 |
|
15 |
|
16 | volatile u8 stx_count;
|
17 | u8 stx_data;
|
18 |
|
19 | volatile u8 srx_done;
|
20 | u8 srx_data;
|
21 | u8 srx_mask;
|
22 | u8 srx_tmp;
|
23 |
|
24 |
|
25 | void suart_init( void )
|
26 | {
|
27 | OCR1A = TCNT1 + 1; // force first compare
|
28 | TCCR1A = 1<<COM1A1^1<<COM1A0; // set OC1A high, T1 mode 0
|
29 | TCCR1B = 1<<ICNC1^1<<CS10; // noise canceler, 1>0 transition,
|
30 | // CLK/1, T1 mode 0
|
31 | TIFR = 1<<ICF1; // clear pending interrupt
|
32 | TIMSK = 1<<TICIE1^1<<OCIE1A; // enable tx and wait for start
|
33 |
|
34 | stx_count = 0; // nothing to sent
|
35 | srx_done = 0; // nothing received
|
36 | STXDDR |= 1<<STX; // TX output
|
37 | }
|
38 |
|
39 |
|
40 | u8 sgetchar( void ) // get byte
|
41 | {
|
42 | while( !srx_done ); // wait until byte received
|
43 | srx_done = 0;
|
44 | return srx_data;
|
45 | }
|
46 |
|
47 |
|
48 | SIGNAL( SIG_INPUT_CAPTURE1 ) // rx start
|
49 | {
|
50 | OCR1B = ICR1 + (u16)(BIT_TIME * 1.5); // scan 1.5 bits after start
|
51 | srx_tmp = 0; // clear bit storage
|
52 | srx_mask = 1; // bit mask
|
53 | TIFR = 1<<OCF1B; // clear pending interrupt
|
54 | if( !(SRXPIN & 1<<SRX)) // still low
|
55 | TIMSK = 1<<OCIE1A^1<<OCIE1B; // wait for first bit
|
56 | }
|
57 |
|
58 |
|
59 | SIGNAL( SIG_OUTPUT_COMPARE1B )
|
60 | {
|
61 | u8 in = SRXPIN; // scan rx line
|
62 |
|
63 | if( srx_mask ){
|
64 | if( in & 1<<SRX )
|
65 | srx_tmp |= srx_mask;
|
66 | srx_mask <<= 1;
|
67 | OCR1B += BIT_TIME; // next bit slice
|
68 | }else{
|
69 | srx_done = 1; // mark rx data valid
|
70 | srx_data = srx_tmp; // store rx data
|
71 | TIFR = 1<<ICF1; // clear pending interrupt
|
72 | TIMSK = 1<<TICIE1^1<<OCIE1A; // enable tx and wait for start
|
73 | }
|
74 | }
|
75 |
|
76 |
|
77 | void sputchar( u8 val ) // send byte
|
78 | {
|
79 | while( stx_count ); // until last byte finished
|
80 | stx_data = ~val; // invert data for Stop bit generation
|
81 | stx_count = 10; // 10 bits: Start + data + Stop
|
82 | }
|
83 |
|
84 |
|
85 | void sputs( u8 *txt ) // send string
|
86 | {
|
87 | while( *txt )
|
88 | sputchar( *txt++ );
|
89 | }
|
90 |
|
91 |
|
92 | SIGNAL( SIG_OUTPUT_COMPARE1A ) // tx bit
|
93 | {
|
94 | u8 dout;
|
95 | u8 count;
|
96 |
|
97 | OCR1A += BIT_TIME; // next bit slice
|
98 | count = stx_count;
|
99 |
|
100 | if( count ){
|
101 | stx_count = --count; // count down
|
102 | dout = 1<<COM1A1; // set low on next compare
|
103 | if( count != 9 ){ // no start bit
|
104 | if( !(stx_data & 1) ) // test inverted data
|
105 | dout = 1<<COM1A1^1<<COM1A0; // set high on next compare
|
106 | stx_data >>= 1; // shift zero in from left
|
107 | }
|
108 | TCCR1A = dout;
|
109 | }
|
110 | }
|