1 | #include "main.h"
|
2 | #include "suart.h"
|
3 |
|
4 |
|
5 |
|
6 | #define BIT_TIME (u8)((XTAL / BAUD) / PRESCALE)
|
7 |
|
8 |
|
9 | volatile u8 stx_count;
|
10 | u8 stx_data;
|
11 |
|
12 | volatile u8 srx_done;
|
13 | u8 srx_data;
|
14 | u8 srx_mask;
|
15 | u8 srx_tmp;
|
16 |
|
17 |
|
18 | void suart_init( void )
|
19 | {
|
20 | SBIT(PORTD,STX) = 1;
|
21 | // OCR0A = TCNT0 + 1; // force first compare
|
22 | // TCCR0A = 0; // Default: Normal port operation
|
23 | TCCR0B = 1 << CS01 | 1<<CS00; // clk/64
|
24 | // TIFR0 = 1<<ICF1; // clear pending interrupt
|
25 | TIMSK0 = 1 << OCIE0A; // enable output compare interrupt
|
26 |
|
27 | EICRA = 1 << ISC01; // falling edge
|
28 | EIMSK = 1 << INT0; // enable edge interrupt
|
29 |
|
30 | stx_count = 0; // nothing to sent
|
31 | srx_done = 0; // nothing received
|
32 | STXDDR |= 1 << STX; // TX output
|
33 | }
|
34 |
|
35 |
|
36 | u8 sgetchar (void) // get byte
|
37 | {
|
38 | while (!srx_done); // wait until byte received
|
39 | srx_done = 0;
|
40 | return srx_data;
|
41 | }
|
42 |
|
43 |
|
44 | ISR (INT0_vect) // rx start
|
45 | {
|
46 | OCR0B = TCNT0 + (u8)((BIT_TIME * 3) / 2);// scan 1.5 bits after start
|
47 |
|
48 | srx_tmp = 0; // clear bit storage
|
49 | srx_mask = 1; // bit mask
|
50 | if( !(SRXPIN & 1<<SRX)) { // still low
|
51 | EIMSK &= ~(1 << INT0); // disable edge interrupt
|
52 | TIMSK0 = 1<<OCIE0A^1<<OCIE0B; // wait for first bit
|
53 | }
|
54 | TIFR0 = 1<<OCF0B; // clear pending interrupt ? why does that output compare int occur?
|
55 | EIFR |= (1 << INTF0); // clear any pending edge interrupt
|
56 | }
|
57 |
|
58 |
|
59 | ISR (TIMER0_COMPB_vect)
|
60 | {
|
61 | u8 in = SRXPIN; // scan rx line
|
62 | // PORTB = 0x00;
|
63 | if (srx_mask) {
|
64 | if (in & 1 << SRX)
|
65 | srx_tmp |= srx_mask;
|
66 | srx_mask <<= 1;
|
67 | OCR0B += BIT_TIME; // next bit slice
|
68 | } else {
|
69 | srx_done = 1; // mark rx data valid
|
70 | srx_data = srx_tmp; // store rx data
|
71 | // TIFR0 = 1<<ICF1; // clear pending interrupt
|
72 | TIMSK0 = 1<<OCIE0A; // enable tx and wait for start
|
73 | EIFR |= (1 << INTF0); // clear any pending edge interrupt: This hinders the in0-vect from beeing triggerd again just now which may occur by falling edges in the serial data bits
|
74 | EIMSK = 1 << INT0; // reenable edge interrupt
|
75 | }
|
76 | // PORTB = 0x02;
|
77 | }
|
78 |
|
79 |
|
80 | void sputchar (u8 val) // send byte
|
81 | {
|
82 | while (stx_count); // until last byte finished
|
83 | stx_data = ~val; // invert data for Stop bit generation
|
84 | stx_count = 10; // 10 bits: Start + data + Stop
|
85 | }
|
86 |
|
87 |
|
88 | void sputs (u8 *txt) // send string
|
89 | {
|
90 | while (*txt)
|
91 | sputchar (*txt++);
|
92 | }
|
93 |
|
94 |
|
95 | ISR (TIMER0_COMPA_vect) // tx bit
|
96 | {
|
97 | u8 dout;
|
98 | u8 count;
|
99 |
|
100 | OCR0A += BIT_TIME; // next bit slice
|
101 | count = stx_count;
|
102 |
|
103 | if (count) {
|
104 | stx_count = --count; // count down
|
105 | // ??? dout = 1<<COM0A1; // set low on next compare
|
106 | dout = 0;
|
107 | if (count != 9) { // no start bit
|
108 | if (!(stx_data & 1)) // test inverted data
|
109 | //??? dout = 1<<COM0A1^1<<COM0A0; // set high on next compare
|
110 | dout = 1;
|
111 | stx_data >>= 1; // shift zero in from left
|
112 | }
|
113 | // TCCR0A = dout;
|
114 | // STX = (dout == 0) ? 1 : 0;
|
115 | SBIT(PORTD,STX) = dout;
|
116 | }
|
117 | }
|