2011-07-20 15:32:52 +00:00
/* USB Keyboard Plus Debug Channel Example for Teensy USB Development Board
* http : //www.pjrc.com/teensy/usb_keyboard.html
* Copyright ( c ) 2009 PJRC . COM , LLC
*
* Permission is hereby granted , free of charge , to any person obtaining a copy
* of this software and associated documentation files ( the " Software " ) , to deal
* in the Software without restriction , including without limitation the rights
* to use , copy , modify , merge , publish , distribute , sublicense , and / or sell
* copies of the Software , and to permit persons to whom the Software is
* furnished to do so , subject to the following conditions :
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software .
*
* THE SOFTWARE IS PROVIDED " AS IS " , WITHOUT WARRANTY OF ANY KIND , EXPRESS OR
* IMPLIED , INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY ,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT . IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM , DAMAGES OR OTHER
* LIABILITY , WHETHER IN AN ACTION OF CONTRACT , TORT OR OTHERWISE , ARISING FROM ,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE .
*/
2010-09-23 11:23:50 +00:00
# include <avr/interrupt.h>
2011-02-07 15:59:31 +00:00
# include "sendchar.h"
2010-09-23 11:23:50 +00:00
# include "usb_debug.h"
// the time remaining before we transmit any partially full
// packet, or send a zero length packet.
volatile uint8_t debug_flush_timer = 0 ;
2011-02-07 15:59:31 +00:00
int8_t sendchar ( uint8_t c )
2010-09-23 11:23:50 +00:00
{
static uint8_t previous_timeout = 0 ;
uint8_t timeout , intr_state ;
// if we're not online (enumerated and configured), error
if ( ! usb_configured ( ) ) return - 1 ;
// interrupts are disabled so these functions can be
// used from the main program or interrupt context,
// even both in the same program!
intr_state = SREG ;
cli ( ) ;
UENUM = DEBUG_TX_ENDPOINT ;
// if we gave up due to timeout before, don't wait again
if ( previous_timeout ) {
if ( ! ( UEINTX & ( 1 < < RWAL ) ) ) {
SREG = intr_state ;
return - 1 ;
}
previous_timeout = 0 ;
}
// wait for the FIFO to be ready to accept data
timeout = UDFNUML + 4 ;
while ( 1 ) {
// are we ready to transmit?
if ( UEINTX & ( 1 < < RWAL ) ) break ;
SREG = intr_state ;
// have we waited too long?
if ( UDFNUML = = timeout ) {
previous_timeout = 1 ;
return - 1 ;
}
// has the USB gone offline?
if ( ! usb_configured ( ) ) return - 1 ;
// get ready to try checking again
intr_state = SREG ;
cli ( ) ;
UENUM = DEBUG_TX_ENDPOINT ;
}
// actually write the byte into the FIFO
UEDATX = c ;
// if this completed a packet, transmit it now!
if ( ! ( UEINTX & ( 1 < < RWAL ) ) ) {
UEINTX = 0x3A ;
debug_flush_timer = 0 ;
} else {
debug_flush_timer = 2 ;
}
SREG = intr_state ;
return 0 ;
}
// immediately transmit any buffered output.
void usb_debug_flush_output ( void )
{
uint8_t intr_state ;
intr_state = SREG ;
cli ( ) ;
if ( debug_flush_timer ) {
UENUM = DEBUG_TX_ENDPOINT ;
while ( ( UEINTX & ( 1 < < RWAL ) ) ) {
UEDATX = 0 ;
}
UEINTX = 0x3A ;
debug_flush_timer = 0 ;
}
SREG = intr_state ;
}