?? io_lite.c
字號:
/***************************************************************************
* This code and information is provided "as is" without warranty of any *
* kind, either expressed or implied, including but not limited to the *
* implied warranties of merchantability and/or fitness for a particular *
* purpose. *
* *
* Copyright (C) 2006 Teridian Semiconductor Corp. All Rights Reserved. *
***************************************************************************/
//**************************************************************************
// DESCRIPTION: 71M651x POWER METER - IO Routines.
//
// AUTHOR: RGV
//
// HISTORY: See end of file
//**************************************************************************
// File: IO_LITE.C
//
// IO subroutines for use by the calibration loader.
//
#include "options.h"
// if the CLI's superior serial logic is available, use it.
#if CAL_LDR && !CLI
#include <ctype.h>
#include "irq.h"
#include "batmodes.h"
#include "main.h"
#include "defaults.h"
#include "meter.h"
#include "io.h" //check definitions against the actual code
#define XON 0x11
#define XOFF 0x13
/* the choice of the hardware abstraction layer (HAL)
* adapts this code to either serial port */
#if SERIAL0
#include "ser0.h" /* include the HAL for UART 0 */
#elif SERIAL1
#include "ser1.h" /* include the HAL for UART 1 */
#else
#error no known serial port selected
#endif
#include "io.h" // test routines here against the interface
uint8_t mpu_div = -1;
uint8_t my_batmode = 0;
bool xmit_rdy;
bool xoff_sent;
#define sbuf 32 // must be a power of two
#define mbuf (sbuf - 1)
uint8_t achRx[sbuf];
uint8d_t ichRxIn, ichRxOut, cchRx;
// lightweight timerless timeout using accumulation intervals
uint32_t my_cai;
bool io_timeout; // the flag read by high level protocols
#pragma save
#pragma NOAREGS
// initialize the serial port, if it's needed
static void init (void) small reentrant
{
if (mpu_div != (CONFIG0 & MPU_DIV) || my_batmode != batmode_is_brownout())
{
uint8_t baud;
irq_disable();
#if SERIAL0
baud = defaults[BAUD0_IDX];
#elif SERIAL1
baud = defaults[BAUD1_IDX];
#else
#error unknown serial port
#endif
#if M6520
if (BATTERY_MODE_ENABLE)
baud = _RATE_300;
#endif
ser_initialize(baud);
mpu_div = CONFIG0 & MPU_DIV;
my_batmode = batmode_is_brownout();
ichRxIn = ichRxOut = cchRx = 0;
xmit_rdy = 0;
xoff_sent = 1;
ser_enable_rcv_rdy(); // enable the receiver interrupt
irq_enable();
my_cai = cai;
io_timeout = 0;
}
}
#pragma restore
// very basic polling output; uses the above serial driver
#pragma save
#pragma NOAREGS
void putc (uint8_t ch) small reentrant
{
init();
// the low level driver is designed so that one can poll
// the TI bit to determine that the transmit buffer is ready
// for another character. Alas, enabling the interrupt
// causes this bit to be reset in the interrupt routine.
while (!xmit_rdy)
{
main_background ();
init();
}
xmit_rdy = 0;
ser_xmit(ch);
}
#pragma restore
bool cmd_pending (void)
{
if (cchRx <= 0)
{
init();
return 0;
}
else
return 1;
}
// very basic interrupting input; uses the above serial driver
#pragma save
#pragma NOAREGS
uint8_t getc (void) small reentrant
{
uint8_t ch;
init ();
if (io_timeout)
return 0;
else
{
my_cai = cai;
while (!cmd_pending())
{
main_background (); // runs everything except serial IO
init ();
if (xoff_sent)
{
putc(XON);
xoff_sent = 0;
}
// little timer that counts accumulation intervals
// This saves the code space of stm.c
if ((cai - my_cai) > 30)
{
io_timeout = 1;
return 0;
}
}
ichRxOut &= mbuf;
ch = achRx[ ichRxOut++ ];
irq_disable();
--cchRx;
irq_enable();
return ch;
}
}
#pragma restore
#pragma save
#pragma NOAREGS
void cli_in (void) small reentrant
{
static uint8_t data rx;
rx = ser_rcv();
// XON/XOFF is handled by sending XON when the calibration loader
// is waiting for a message, and sending XOFF after the message's
// checksum is received. This is just a buffering arrangement
// so the PC's driveling isn't lost
if (XON != rx && XOFF != rx && cchRx < sbuf)
{
ichRxIn &= mbuf;
achRx[ ichRxIn++ ] = rx;
irq_disable();
++cchRx;
irq_enable();
if (cchRx > (sbuf/4) && xmit_rdy && !xoff_sent)
{
xmit_rdy = 0;
ser_xmit(XOFF);
xoff_sent = 1;
}
}
}
#pragma restore
#pragma save
#pragma NOAREGS
// the low level driver is designed so that one can poll
// the TI bit to determine that the transmit buffer is ready
// for another character. Alas, enabling the interrupt
// causes an interrupt when TI is set, because there is no
// separate enable bit for the transmit interrupt.
void cli_out (void) small reentrant
{
xmit_rdy = 1;
ser_disable_xmit_rdy();
}
#pragma restore
// Send single ASCII hex or decimal digit to DTE.
static void send_digit (uint8_t c)
{
if (c > 9)
c += 'A' - 10;
else
c += '0';
putc ( c );
}
void send_hex (uint8_t c)
{
send_digit (c >> 4);
send_digit (c & 0x0F);
}
// Send ROM string out PC UART.
#pragma save
#pragma NOAREGS
void start_tx_rslt (uint8r_t *pc) small reentrant
{
uint8_t c;
c = *pc;
while (c)
{
putc ( c );
++pc;
c = *pc;
}
}
#pragma restore
#undef NULL
#undef LF
#undef CRET
#define NULL 0x00
#define LF 0x0A // LINE FEED
#define CRET 0x0D // CARRIAGE RETURN
static uint8r_t v_crlf[] = { CRET, LF, NULL };
#pragma save
#pragma NOAREGS
void send_crlf (void) small reentrant // Send <CR><LF> out PC UART.
{
start_tx_rslt (v_crlf);
}
#pragma restore
// Get next hexadecimal digit.
#undef CASE_
#define CASE_ 0x20
static uint8_t rcv_digit (void)
{
uint8_t c;
do {
c = getc ();
if (io_timeout)
return 0;
} while (!isxdigit(c));
c -= '0'; // '0' mapped to 0;
if (c >= 10)
{
c &= ~CASE_;
c -= 'A' - '0' - 10; // 'A' mapped to 10.
}
return (c);
}
uint8_t rcv_hex (void) // Convert ascii hexdecimal byte to binary
{
return ((rcv_digit () << 4) | rcv_digit ());
}
/***************************************************************************
* History:
* $Log: io_lite.c,v $
* Revision 1.12 2006/03/10 00:03:40 tvander
* Now selects its BAUD rate using DIO_8 for the 6520.
*
* Revision 1.11 2006/09/09 01:09:37 gmikef
* *** empty log message ***
*
* Revision 1.10 2006/08/16 01:43:08 tvander
* Only send one XOFF
*
* Revision 1.9 2006/08/09 00:56:34 tvander
* *** empty log message ***
*
* Revision 1.8 2006/07/28 02:45:23 tvander
* Fixed missing XON
*
* Revision 1.7 2006/07/25 00:27:59 tvander
* Added timeout
*
* Revision 1.6 2006/07/19 01:53:08 tvander
* Modified to do XON/XOFF
*
* Revision 1.5 2006/07/18 20:32:19 tvander
* Quick & Dirty XON/XOFF scheme
*
* Revision 1.4 2006/07/07 00:53:44 tvander
* Modified lightweight IO to change baudrates to adapt to clock changes.
*
* Revision 1.3 2006/06/08 18:24:55 tvander
* Removed call to background
*
* Revision 1.2 2006/06/06 03:56:27 tvander
* A lame substitute for io.c, but very compact.
*
* Revision 1.1 2006/05/27 01:35:05 tvander
* *** empty log message ***
*
*
* 2006 May 25; First Version.
* Copyright (C) 2006 Teridian Semiconductor Corp. All Rights Reserved. *
* this program is fully protected by the United States copyright *
* laws and is the property of Teridian Semiconductor Corporation. *
***************************************************************************/
#endif
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -