Subversion Repositories Projects

Compare Revisions

Ignore whitespace Rev 1931 → Rev 1932

/Transportables_Koptertool/branch/PKT/branch/GPL_PKT_V3_6_7f_FC090b/wi232/Text File
0,0 → 1,177
// wi232.c:
//
// Call fopen_wi232() to set up the wi232 as an input output data stream.
// If fopen_wi232() is the first fopen command called, then the wi232
// becomes stdin and stdout and stderr.
// The
//
// Uses Interupts to handle data streaming. The wi232 uses USART0, which uses:
// Rx = PORTE0 = pin 2
// Tx = PORTE1 = pin 3
// CTS = PORTE2 = pin 4
#include <inttypes.h>
#include <stdio.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/signal.h>
 
#include "wi232.h"
#include "circularqueue.h"
#include "usart.h"
 
const int _baud_rate_c = 38400;
const int _tx_buffer_size_c = 256;
const int _rx_buffer_size_c = 256;
const uint8_t _cts_pin_c = _BV( PINE2 );
 
volatile char wi232_tx_buffer[ _tx_buffer_size_c ];
volatile char wi232_rx_buffer[ _rx_buffer_size_c ];
 
// circular queues used for the USART
CircularQueue< volatile char > wi232_tx_q( wi232_tx_buffer, _tx_buffer_size_c );
CircularQueue< volatile char > wi232_rx_q( wi232_rx_buffer, _rx_buffer_size_c );
 
// prototype
int wi232_putchar( char );
int wi232_getchar();
void initialize_baud_rate();
void command( bool enable );
void write_register( uint8_t reg, uint8_t value );
bool _cts();
 
// use BAUD_RATE baud 8N1 RX & TX on USART0
// to transmit to the wi232
FILE* fopen_wi232()
{
// enable Rx, Tx & Rx interupt
// (Tx buffer empty interupt is enabled when we actually send something)
UCSR0B = _BV( RXEN0 ) |
_BV( TXEN0 ) |
_BV( RXCIE0 );
// UCSC00 = 1 & UCSC01 = 1 -> 8-bit data
UCSR0C = _BV( UCSZ00 ) | _BV( UCSZ01 );
initialize_baud_rate();
wi232_tx_q.clear();
wi232_rx_q.clear();
 
// set wi232_putchar as the stdout stream character Tx-er
// set wi232_getchar as the stdin stream chacacter Rx-er
return fdevopen( wi232_putchar, wi232_getchar, 0 );
}
 
inline void initialize_baud_rate()
{
// enable command pin as output
DDRE |= _BV( PORTE3 );
command( true );
usart0_set_baud_rate( 2400 );
sei();
write_register( 78, 3 ); // set baud rate to 38400
wait(100);
cli();
usart0_set_baud_rate( 38400 );
command( false );
}
 
inline void command( bool enable )
{
if ( enable )
PORTE &= ~_BV( PORTE3 );
else
PORTE |= _BV( PORTE3 );
}
 
inline void write_register( uint8_t reg, uint8_t value )
{
if ( value < 0x80 )
{
// data = [ 0xFF, 2, reg, value ]
wi232_putchar( 0xFF );
wi232_putchar( 2 );
wi232_putchar( reg );
wi232_putchar( value );
}
else // value >= 0x80
{
// data = [ 0xFF, 3, reg, 0xFE, (value - 0x80) ]
wi232_putchar( 0xFF );
wi232_putchar( 3 );
wi232_putchar( reg );
wi232_putchar( 0xFE );
wi232_putchar( value - 0x80 );
}
}
 
int wi232_putchar( char x )
{
wi232_tx_q.put( x );
// enable the "data register empty" interupt
// (it may already be enabled in which case no harm is done)
UCSR0B |= _BV( UDRIE0 );
 
// return -1 if overflow is true, otherwise return 0
// return wi232_tx_q.overflow() ? -1 : 0;
return 0; // for now, screw overflow - just ignore it
}
 
int wi232_getchar()
{
// wait until the queue is no longer empty
while ( wi232_rx_q.is_empty() );
 
char x = wi232_rx_q.get();
return x;
}
 
uint16_t wi232_data_available()
{
return wi232_rx_q.length();
}
 
bool wi232_is_empty()
{
return wi232_rx_q.is_empty();
}
 
// returns true when CTS is low,
// i.e. it is true when it is okay to send data
inline bool _cts()
{
return !(PINE & _cts_pin_c);
}
 
// we received some data on USART0
// put this data into the received data queue
SIGNAL( SIG_UART0_RECV )
{
wi232_rx_q.put( UDR0 );
}
 
// the USART is ready to queue another byte to send
SIGNAL( SIG_UART0_DATA )
{
if ( !wi232_tx_q.is_empty() )
{
if ( !_cts() )
{
sei();
// wait until CTS is true
while ( !_cts() );
}
 
// if the queue is not empty, put the next character in the buffer
// this also resets the interupt flag automatically
UDR0 = wi232_tx_q.get();
}
else
{
// disable the interupt
UCSR0B &= ~_BV( UDRIE0 );
}
}