Subversion Repositories Projects

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1920 - 1
 
2
// wi232.c:
3
//
4
// Call fopen_wi232() to set up the wi232 as an input output data stream.
5
// If fopen_wi232() is the first fopen command called, then the wi232
6
// becomes stdin and stdout and stderr.
7
// The
8
//
9
// Uses Interupts to handle data streaming. The wi232 uses USART0, which uses:
10
// 		Rx 	= PORTE0 = pin 2
11
//		Tx 	= PORTE1 = pin 3
12
//		CTS	= PORTE2 = pin 4
13
 
14
#include <inttypes.h>
15
#include <stdio.h>
16
#include <avr/io.h>
17
#include <avr/interrupt.h>
18
#include <avr/signal.h>
19
 
20
#include "wi232.h"
21
#include "circularqueue.h"
22
#include "usart.h"
23
 
24
const int		_baud_rate_c		= 38400;
25
const int		_tx_buffer_size_c	= 256;
26
const int		_rx_buffer_size_c	= 256;
27
const uint8_t _cts_pin_c			= _BV( PINE2 );
28
 
29
volatile char wi232_tx_buffer[ _tx_buffer_size_c ];
30
volatile char wi232_rx_buffer[ _rx_buffer_size_c ];
31
 
32
// circular queues used for the USART
33
CircularQueue< volatile char > wi232_tx_q( wi232_tx_buffer, _tx_buffer_size_c );
34
CircularQueue< volatile char > wi232_rx_q( wi232_rx_buffer, _rx_buffer_size_c );
35
 
36
// prototype
37
int wi232_putchar( char );
38
int wi232_getchar();
39
void initialize_baud_rate();
40
void command( bool enable );
41
void write_register( uint8_t reg, uint8_t value );
42
bool _cts();
43
 
44
// use BAUD_RATE baud 8N1 RX & TX on USART0
45
// to transmit to the wi232
46
FILE* fopen_wi232()
47
{
48
	// enable Rx, Tx & Rx interupt
49
	// (Tx buffer empty interupt is enabled when we actually send something)
50
	UCSR0B = _BV( RXEN0 )	|
51
	         _BV( TXEN0 )	|
52
			 _BV( RXCIE0 );
53
 
54
	// UCSC00 = 1 & UCSC01 = 1 -> 8-bit data
55
	UCSR0C = _BV( UCSZ00 ) | _BV( UCSZ01 );
56
 
57
	initialize_baud_rate();
58
	wi232_tx_q.clear();
59
	wi232_rx_q.clear();
60
 
61
	// set wi232_putchar as the stdout stream character Tx-er
62
	// set wi232_getchar as the stdin  stream chacacter Rx-er
63
	return fdevopen( wi232_putchar, wi232_getchar, 0 );
64
}
65
 
66
inline void initialize_baud_rate()
67
{
68
	// enable command pin as output
69
	DDRE |= _BV( PORTE3 );
70
	command( true );
71
	usart0_set_baud_rate( 2400 );
72
	sei();
73
	write_register( 78, 3 ); // set baud rate to 38400
74
	wait(100);
75
	cli();
76
	usart0_set_baud_rate( 38400 );
77
	command( false );
78
}
79
 
80
inline void command( bool enable )
81
{
82
	if ( enable )
83
		PORTE	&= ~_BV( PORTE3 );
84
	else
85
		PORTE	|= _BV( PORTE3 );
86
}
87
 
88
inline void write_register( uint8_t reg, uint8_t value )
89
{
90
	if ( value < 0x80 )
91
	{
92
		// data = [ 0xFF, 2, reg, value ]
93
		wi232_putchar( 0xFF );
94
		wi232_putchar( 2 );
95
		wi232_putchar( reg );
96
		wi232_putchar( value );
97
	}
98
	else // value >= 0x80
99
	{
100
		// data = [ 0xFF, 3, reg, 0xFE, (value - 0x80) ]
101
		wi232_putchar( 0xFF );
102
		wi232_putchar( 3 );
103
		wi232_putchar( reg );
104
		wi232_putchar( 0xFE );
105
		wi232_putchar( value - 0x80 );
106
	}
107
}
108
 
109
int wi232_putchar( char x )
110
{
111
	wi232_tx_q.put( x );
112
 
113
	// enable the "data register empty" interupt
114
	// (it may already be enabled in which case no harm is done)
115
	UCSR0B |= _BV( UDRIE0 );
116
 
117
	// return -1 if overflow is true, otherwise return 0
118
	// return wi232_tx_q.overflow() ? -1 : 0;
119
	return 0; // for now, screw overflow - just ignore it
120
}
121
 
122
int wi232_getchar()
123
{
124
	// wait until the queue is no longer empty
125
	while ( wi232_rx_q.is_empty() );
126
 
127
	char x = wi232_rx_q.get();
128
	return x;
129
}
130
 
131
uint16_t wi232_data_available()
132
{
133
	return wi232_rx_q.length();
134
}
135
 
136
bool wi232_is_empty()
137
{
138
	return wi232_rx_q.is_empty();
139
}
140
 
141
// returns true when CTS is low,
142
// i.e. it is true when it is okay to send data
143
inline bool _cts()
144
{
145
	return !(PINE & _cts_pin_c);
146
}
147
 
148
// we received some data on USART0
149
// put this data into the received data queue
150
SIGNAL( SIG_UART0_RECV )
151
{
152
	wi232_rx_q.put( UDR0 );
153
}
154
 
155
// the USART is ready to queue another byte to send
156
SIGNAL( SIG_UART0_DATA )
157
{
158
	if ( !wi232_tx_q.is_empty() )
159
	{
160
		if ( !_cts() )
161
		{
162
			sei();
163
			// wait until CTS is true
164
			while ( !_cts() );
165
		}
166
 
167
		// if the queue is not empty, put the next character in the buffer
168
		// this also resets the interupt flag automatically
169
		UDR0 = wi232_tx_q.get();
170
	}
171
	else
172
	{
173
		// disable the interupt
174
		UCSR0B &= ~_BV( UDRIE0 );
175
	}
176
}
177