add unified compile target
[avr_work.git] / lline / spi_io.c
blobdb16773081eab782a7d9ab9ae6e606241ac592d6
2 #include <stdio.h>
4 #include <avr/io.h>
5 #include <avr/power.h>
6 #include <avr/interrupt.h>
8 #include "common.h"
9 #include "queue.h"
11 #include "spi_io.h"
13 /*
14 ATtinyX61:
15 DI -> 0
16 DO -> 1
17 CLK-> 2
20 #define I_DI 0
21 #define I_DO 1
22 #define I_CLK 2
24 #define USI_PORT B
26 #define NEGATIVE 1
27 #define POSITIVE 0
28 #define SPI_EDGE POSITIVE
30 uint8_t tx_b[32], rx_b[32];
31 queue_t tx = Q_INIT(tx_b);
32 queue_t rx = Q_INIT(rx_b);
34 #define spi_isr_on() (USICR |= (1<<USIOIE))
35 #define spi_isr_off() (USICR &= (uint8_t)~(1<<USIOIE))
37 #ifdef SPI_IO_STANDARD
38 int spi_putc(char c, FILE * stream);
39 int spi_getc(FILE * stream);
40 static FILE _spi_io = FDEV_SETUP_STREAM(spi_putc, spi_getc ,_FDEV_SETUP_RW);
41 #endif
43 void spi_io_init(void) {
44 power_usi_enable();
46 // Clr the flags we interupt on + counter bits in same reg.
47 // (default is not raised)
48 //USISR = (1<<USIOIF);
50 // Clr datareg to avoid junk data being sent out. (defaults to 0)
51 //USIDR = 0;
54 #define B 0
55 #define A 1
56 #if ( USI_PORT == B )
57 //#warning Using Port B (default)
58 //USIPP &= (uint8_t)~(1<<USIPOS);
59 #else
60 #error Using Port A
61 USIPP |= (1<<USIPOS);
62 #endif
63 #undef A
64 #undef B
66 DDR(USI_PORT) |= (1<<I_DO);
67 DDR(USI_PORT) &= (uint8_t)~((1<<I_DI)|(1<<I_CLK));
68 PORT(USI_PORT)&= (uint8_t)~( (1<<I_DI) | (1<<I_CLK) | (1<<I_DO) );
70 USICR = (0<<USISIE) | // Start IE(2w), CLK edge IE(3w)
71 (1<<USIOIE) | // Ovf interupt (to refil register)
72 (0<<USIWM1) | (1<<USIWM0) | // 01 = 3w, 00 = disable, 10&11 = 2w
73 (1<<USICS1) | (SPI_EDGE<<USICS0) | // 10 = positive edge, 11 = neg.
74 (0<<USICLK) | // 4bit timer : 0 = external, 1 = sw
75 (0<<USITC ); // Clock toggle
77 #ifdef SPI_IO_STANDARD
78 spi_io = & _spi_io;
79 #endif
83 ISR( SIG_USI_OVERFLOW ) {
84 USISR = (1<<USIOIF); // Clear interupt flag and counter.
86 //transmit (tx)
87 if (!q_empty(&tx)) {
88 USIDR = q_pop(&tx);
90 else USIDR = 0;
92 //recieve (rx)
93 uint8_t in = USIBR;
94 if (in != 0 && !q_full(&rx)) {
95 q_push(&rx,in);
96 if (in == '\n')
97 spi_io_rx_nl++;
100 /*// Alternate if we don't care about losing old data.
101 if (USIBR != 0) {
102 q_push_o(&rx,USIBR);
108 #ifdef SPI_IO_STANDARD
109 int spi_putc(char c, FILE * stream) {
110 int r;
111 spi_isr_off();
112 //while(q_full(&tx));
113 if (q_full(&tx))
114 r = EOF;
115 else
116 r = q_push(&tx,(uint8_t)c);
117 spi_isr_on();
118 return r;
122 int spi_getc(FILE * stream) {
123 int r;
124 spi_isr_off();
125 //while(q_empty(&rx));
126 if (q_empty(&rx))
127 r = EOF;
128 else
129 r = q_pop(&rx);
130 spi_isr_on();
131 return r;
133 #endif
135 int spi_getchar(void) {
136 int r;
137 spi_isr_off();
138 //while(q_empty(&rx));
139 if (q_empty(&rx))
140 r = EOF;
141 else
142 r = q_pop(&rx);
143 spi_isr_on();
144 return r;
147 void spi_puts(const char * string) {
148 spi_isr_off();
149 while(*string) {
150 _spi_putchar(*string);
151 string++;
153 spi_isr_on();
156 void spi_o_puts(const char * string) {
157 spi_isr_off();
158 while(*string) {
159 if(q_full(&tx)) {
160 spi_isr_on();
161 asm(
162 "nop\n\t"
163 "nop\n\t"
164 "nop"
166 spi_isr_off();
168 q_push_o(&tx,*string);
169 string++;
171 spi_isr_on();
174 static inline uint8_t hex2ascii(uint8_t hex) {
175 hex = 0x0F & hex;
176 hex = (uint8_t) (hex + '0');
177 if (hex > '9')
178 return (uint8_t) (hex + 7); // 7 characters between nums and caps.
179 else
180 return hex;
183 static inline void _spi_putchar(uint8_t ch) {
184 // expects spi interupt disabled on entry, leaves it disabled on exit.
185 while(q_full(&tx)) {
186 spi_isr_on();
187 asm(
188 "nop\n\t"
189 "nop"
191 spi_isr_off();
193 q_push(&tx,ch);
196 void spi_putchar(uint8_t ch) {
197 spi_isr_off();
198 _spi_putchar(ch);
199 spi_isr_on();
202 void spi_puth(uint8_t hex) {
203 spi_isr_off();
205 _spi_putchar( hex2ascii( (hex>>4 ) ) );
206 _spi_putchar( hex2ascii( (hex>>0 ) ) );
208 spi_isr_on();
211 void spi_puth2(uint16_t hex) {
212 spi_isr_off();
214 _spi_putchar( hex2ascii( (uint8_t)(hex>>12) ) );
215 _spi_putchar( hex2ascii( (uint8_t)(hex>>8 ) ) );
216 _spi_putchar( hex2ascii( (uint8_t)(hex>>4 ) ) );
217 _spi_putchar( hex2ascii( (uint8_t)(hex>>0 ) ) );
219 spi_isr_on();