File "main.c"
Full Path: /home/analogde/www/private/Projet/main.c
File size: 25.18 KB
MIME-type: text/x-c
Charset: 8 bit
/* ===========================================================================
Main.c - Simple ?? program for Axiom CML12SDP256 board
Version: 1.0
Author: Jason Siegel
Compiler: GNU for 68HC11 & 68HC12 (www.gnu-m68hc11.org)
This is freeware - use as you like
==============================================================================
------------------------------------------------------------------------------
*/
// Constant Definitions
// --------------------
#define Eclock 24000000 // 24Mhz crystal clock frequency (NOICE)
//#define Eclock 8000000 // 8Mhz crystal clock frequency (MON12)
// this board has a 4Mhz osc clock
//#define CLKX ((Eclock/1000000)/4) - 1 // pll enable for Eclock
#define CLKX 0x05
// values for baud registers, based on clock frequency.
#define Baud115200 (Eclock/16)/115200
#define Baud57600 (Eclock/16)/57600
#define Baud38400 (Eclock/16)/38400
#define Baud19200 (Eclock/16)/19200
#define Baud9600 (Eclock/16)/9600
#define ARRAYSIZE 40
#define SENDFLAG 4
// 1488
//SPI STATUS REGISTER
#define SPTEF 0x20
#define SPIF 0x80
#include "..\ports_d256.h"
#include "lcd.h"
#include "keypad.h"
#include "serial.h"
// RAM Variables
// -------------
unsigned long timeout1; // general purpose timeout.
unsigned int count1; // general purpose counter
unsigned int count4; // general purpose counter
unsigned int count5;
unsigned int TC6Val; // output compare timer value
unsigned char Sflag;
unsigned char Sec15flag;
unsigned int Npulses=0;
unsigned int Last_Npulses=0;
unsigned char R_data=0;
int Last_serial_status;
int spare_index=0;
char keyval;
unsigned long ELEC_COST=3265; //electric cost * 100000
unsigned char min=0x58, sec=0x0, hr=0x09, dow=0x04, date=0x23, mon=0x10, yr=0x03;
char output[40];
// i SHould put this in external SRAM so that the data is saved if the power goes out.
struct _timedate {
unsigned char sec;
unsigned char min;
unsigned char hour;
unsigned char day;
unsigned int N_counts_interval;
} timestamp[ARRAYSIZE];
int Current_index;
unsigned char month=11; //not yet implemented
unsigned int year=2004; //not yet implemented
long Current_cost;
// Function Prototypes
// -------------------
void end_here();
void SER_RECEIVE() __attribute__((interrupt));
void TOC6Handle() __attribute__((interrupt));
void InitPLL();
void setup_stuff();
void setup_SPI1();
void init_DS1305();
void reset_spi(void);
void wbyte_spi(unsigned char);
unsigned char rbyte_spi(void);
void write_serial();
long Calc_Proj_cost(int Nseg, int i);
void Calc_Curr_cost(int i);
int twokey_DS1305_num(char keys[2]);
int key_num(char key);
main(){
long i=0;
int couner_ii=0;
int indexD=0;
/*
input Target cost < $1000
Cost of Electricity ~0.000001
Time on clock.
Year Month Day(1-31) hour min sec
OUTPUT Data Array:
Projected Cost. * Project=Current_cost/Nseg* Nseg_month
Current Cost * can be calculated on demand. SUM(N_counts_interval(i) * cost of elect) up to i
Day
Hour
Min
N_counts in Interval
At current rate of consumption what is the project cost for the end of the month.
STOP Running after 10 mins taking data
Only Print out data thru Current date, since begin of Month.
Write a float to ascii funtion. or find one
Use DS1305 interrupt to control timing, alarm every sec, count to 15....
*/
asm("sei"); // disable interrupts
InitPLL(); // Initialize PLL
// Initialize Virtual Interrupt Vectors for ruhning under serial debugger (MON12/NOICE)
*(void(**)())0x3fe2 = TOC6Handle; // set Timer Output Compare 7 vector
*(void(**)())0x3fD6 = SER_RECEIVE; // set interrupt routine for Serial Reviever $FFD6
// *(void(**)())0x3fCC = PortHhandle; // set interrupt routine for Serial Reviever $FFD6
//InitSerial(Baud9600); // Initialize Serial Port 1 Baud rate
InitSerial(Baud115200);
//InitATD(); //this funtion sets up the A/D. no longer used.
setup_stuff(); //this funtion sets up the couter timer, and pulse accumulator.
setup_SPI1(); //setup serial interface to DS1305
unsigned char ioport = 0; // default output to port sci0
puts("\nYou should see PT6 toggling at 500us ");
LCDInit(); // initialize LCD
InitKeypad();
// prompt user for date and time. supply current settings.
init_DS1305(); //set date and time.
asm("cli"); // enable interrupts
lcd_cmd(0x01); // clear display and home cursor
for (i=0; i<48000;i++); //wait 2ms
// prompt for engery cost and spending goal.
LCDputs("Set Elec Cost? Y/N: ");
keyval= getkeypad();
if(keyval=='9'){
ELEC_COST=0;
couner_ii=0;
LCDputs("Use 5 digits ");
LCDputs("Enter Rate*100,000 ");
LCDputs(":");
do{
keyval= getkeypad();
LCDputch(keyval);
if( keyval !='#' ) ELEC_COST= 10*ELEC_COST + key_num(keyval);
couner_ii++;
} while( (couner_ii < 5) && ( keyval !='#' ) );
}
lcd_cmd(0x01); // clear display and home cursor
for (i=0; i<48000;i++); //wait 2ms
// endless loop
while(1){
if(Sflag == 1){ // if time expired 1/2 sec
Sflag=0;
lcd_cmd(0x02); //Cursor to Home
asm("sei"); // disable interrupts
Npulses=PACN2+(PACN3<<4); //this line reades the Pulse accumulator.
// LCDputs("here every sec ");
PTT = 0x0001; // enable RTC - CS high
wbyte_spi(0); // seconds register read address
rbyte_spi(); // dummy read
wbyte_spi(0);
sec = rbyte_spi(); // read seconds register
wbyte_spi(0);
min = rbyte_spi(); // ditto minutes
wbyte_spi(0);
hr = rbyte_spi(); // and so on
wbyte_spi(0);
dow = rbyte_spi();
wbyte_spi(0);
date = rbyte_spi();
wbyte_spi(0);
mon = rbyte_spi();
wbyte_spi(0);
yr = rbyte_spi();
PTT = 0; // disable RTC - CS low
asm("cli"); // enable interrupts
sec=((sec & 0xF0)>>4)*10+(sec & 0xF);
min=((min & 0xF0)>>4)*10+(min & 0xF);
hr=((hr & 0x30)>>4)*10+(hr & 0xF);
date=((date & 0xF0)>>4)*10+(date & 0xF);
//itoa(date,output);
//LCDputs(output); LCDputs("-Date ");
itoa(hr,output);
LCDputs(output); LCDputs(":");
itoa(min,output);
LCDputs(output); LCDputs(":");
itoa(sec,output);
LCDputs(output); LCDputs(" Counts:");
//itoa(count1,output);
itoa(Npulses-Last_Npulses,output);
LCDputs(output); LCDputs(" ");
// store 1 value Every 15 secs
if(sec%15==0 && Sec15flag==0 && (indexD < ARRAYSIZE)){
// here every 15 secs
Sec15flag=1;
timestamp[indexD].N_counts_interval= Npulses-Last_Npulses;
timestamp[indexD].sec=sec;
timestamp[indexD].min=min;
timestamp[indexD].hour=hr;
indexD++;
Last_Npulses=Npulses;
//if (indexD>ARRAYSIZE) indexD=0; //start a new month. // fix when we add DS1305
write_serial();
}
if(sec%15==1) Sec15flag=0; // we dont want to run 2x per
++count1;
}
}
}
void end_here(){
return; // this is here for a constant place to put a breakpoint
}
//---------------------------------------------------------------------------
// change the clock frequency using the PLL
void InitPLL(){
unsigned char stat;
// Enable the PLL
SYNR = CLKX; // set Eclock frequency
do{ // wait for PLL to lock...
stat = CRGFLG; // get PLL flags
}while((stat & 0x08) == 0);
CLKSEL = 0x80; // turn PLL on
}
//=== INTERRUPT ROUTINES =====================================================
/*----------------------------------------------------------------------------
TOC6Handle
----------
Interrupt Handler routine for TOC6
----------------------------------------------------------------------------*/
void __attribute__((interrupt))TOC6Handle(){
// here every 500us
TFLG1 = 0x40; // clear C6 output capture flag - IDLE
TC6 = TC6 + TC6Val; // Set new Timer 6 Output compare Value
++timeout1; // incriment timeout counter
if(++count4 > 1000){ // if time to update counters
// here every 1/2 second
// senddata_flag++;
Sflag=1;
count4=0;
}
}
void __attribute__((interrupt)) SER_RECEIVE(){
// asm("sei"); // disable interrupts
//char data[40];
Last_serial_status=SC0SR1;
if(Last_serial_status & 0x20 )
{// there is something in the Recieve Data Register
R_data=SC0DRL;
// putch(R_data); //echo back to host
if ( R_data=='g' )
{
write_serial();
}
else if ( R_data=='d' )
{
reset();
}
}
}
//=== END INTERRUPT ROUTINES ==================================================
void setup_stuff()
{
// Initialize Timers
// BUS SPEED - Eclock
// On this board (CML12DP256) on power up, the bus clock defaults to 2Mhz (osc / 2)
// operating MON12 debugger the bus clock is running at 8Mhz
// operating NoICE kernel the bus clock is running at 24Mhz
// TMSK2 (now called TSCR2 in the new datasheet) changes the timer PRESCALER
TMSK2 = 0x00; // Prescaler divide by 1 (TSCR2) - makes timer system run at Bus speed exactly (no prescaler)
// TMSK2 = 0x01; // Prescaler divide by 2 (TSCR2) - makes timer system run at Bus speed / 2
// TMSK2 = 0x03; // Prescaler divide by 8 (TSCR2) - makes timer system run at Bus speed / 8
// TMSK2 = 0x04; // Prescaler divide by 16 (TSCR2) - makes timer system run at Bus speed / 16 (ie. 24/16 = 1.5)
// TMSK2 = 0x05; // Prescaler divide by 32 (TSCR2) - makes timer system run at Bus speed / 32
TSCR = 0x80; // enable timer
/*
1/bus speed = time period (half cycle time)
IF USING NO PRESCALER:
1/24 = 0.041667 (41.7 nano-seconds)
we want 500us, so 500 / 0.041667 = 12000
this will give us a 500us time period (half cycle time)
IF USING divide by 2 prescaler (TMSK2=0x01)
1/12 = 0.083333 (83.3 nano-seconds)
we want 500us, so 500 / 0.083333 = 6000
this will give us a 500us time period (half cycle time)
*/
TC6Val = 12000; // output compare time with NO prescaler (24mhz)
// TC7Val = 6000; // output compare time with /2 prescaler
TC6 = TCNT + TC6Val; // Set Timer 6 Output compare Value
TIOS = 0x40; // set channel 6 to output compare
TCTL1 = 0x40; // toggle OC7 output line on output compare
TMSK1 = 0x40; // enable Channel 6 Interrupt Request (TIE)
TFLG1 = 0x40; // clear C6 output capture flag - IDLE
TFLG2 = 0x00; // clear timer overflow flag
DDRT=0x01;// USE T0 for output to control DS1305
// Here is where we setup the pulse accumulator on channel T7
// we want negative edge and to disable interrupts
PACTL=0x40; //This register contains all settings for Pulse accumulator A.
// see section 3.3.15 PACTL 16-Bit Pulse Accumulator A Control Register
// of ECT_16B8C Block User Guide for register descriptions
// reset all counters and flags
count1=0;
count4=0;
timeout1=0;
Sflag=0;
}
void setup_SPI1(){
// SPI Port 1 uses PP0-4
// PP3 SS1 Serial Peripheral Interface 1 slave select output in master mode,
// input for slave mode or master mode.
// PP2 SCK1 Serial Peripheral Interface 1 serial clock pin
// PP1 MOSI1 Serial Peripheral Interface 1 master out/slave in pin
// PP0 MISO1 Serial Peripheral Interface 1 master in/slave out pin
// #define SPI1CR1 _P(0xF0) // spi 1 control1 reg
// #define SPI1CR2 _P(0xF1) // spi 1 control2 reg
// #define SPI1BR _P(0xF2) // spi 1 baud reg
// #define SPI1SR _P(0xF3) // spi 1 status reg hi
// #define SP1DR _P(0xF5) // spi 1 data reg
// 3.3.1 SPI Control Register 1
// Register Address: $___0
// Bit 7 6 5 4 3 2 1 Bit 0
// SPIE SPE SPTIE MSTR CPOL CPHA SSOE LSBFE
// Reset: 0 0 0 0 0 1 0 0
// LCD 0 1 0 1 0 0 1 0 0x52;
// desired 0 1 0 1 0 1 0 0 0x54;
// SPIE SPI Interrupt Enable Bit
// This bit enables SPI interrupts each time the SPIF or MODF status flag is set.
// 1 = SPI interrupts enabled.
// 0 = SPI interrupts disabled.
// SPE SPI System Enable Bit
// This bit enables the SPI system and dedicates the SPI port pins to SPI system functions.
// 1 = SPI port pins are dedicated to SPI functions.
// 0 = SPI disabled (lower power consumption).
// SPTIE SPI Transmit Interrupt Enable
// This bit enables SPI interrupt generated each time the SPTEF flag is set.
// 1 = SPTEF interrupt enabled.
// 0 = SPTEF interrupt disabled.
// MSTR SPI Master/Slave Mode Select Bit
// 1 = Master mode
// 0 = Slave mode
// CPOL SPI Clock Polarity Bit
// This bit selects an inverted or non-inverted SPI clock. To transmit data between SPI modules, the SPI
// modules must have identical CPOL values.
// 1 = Active-low clocks selected; SCK idles high
// 0 = Active-high clocks selected; SCK idles low
// CPHA SPI Clock Phase Bit
// This bit is used to shift the SCK serial clock.
// 1 = The first SCK edge is issued at the beginning of the 8-cycle transfer operation
// 0 = The first SCK edge is issued one-half cycle into the 8-cycle transfer operation
// SSOE Slave Select Output Enable
// The SS output feature is enabled only in the master mode by asserting the SSOE as shown in Table
// MOD
// FEN SSOE Master Mode Slave Mode
// 0 0 SS not used by SPI SS input
// 0 1 SS not used by SPI SS input
// 1 0 SS input with MODF feature SS input
// 1 1 SS output SS input
// LSBFE SPI LSB-First Enable
// This bit does not affect the position of the msb and lsb in the data register. Reads and writes of the data
// register always have the msb in bit 7.
// 1 = Data is transferred least significant bit first.
// 0 = Data is transferred most significant bit first.
// 3.3.2 SPI Control Register 2
// Register Address: $___1
// Bit 7 6 5 4 3 2 1 Bit 0
// 0 0 0 MODFEN BIDIROE 0 SPISWAI SPC0
// Reset: 0 0 0 0 0 0 0 0
// LCD 0 0 0 1 0 0 0 0
// MODFEN Mode Fault Enable Bit
// This bit when set allows the MODF flag to be set. If the MODF flag is set, clearing the MODFEN does
// not clear the MODF flag. If the SPI is enabled as master and the MODFEN bit is low, then the SS pin
// is not used by the SPI.
// When the SPI is enabled as a slave, the SS is available only as an input regardless of the value of
// MODFEN.
// 1 = Enable setting the MODF error
// 0 = Disable the MODF error
// BIDIROE Output enable in the Bidirectional mode of operation
// This bit along with the MSTR bit of SPCR1 is used to enable the output buffer when the SPI is
// configured in bidirectional mode.
// 1 = Output buffer enabled
// 0 = Output buffer disabled
// SPISWAI SPI Stop in Wait Mode Bit
// This bit is used for power conservation while in wait mode.
// 1 = Stop SPI clock generation when in wait mode
// 0 = SPI clock operates normally in wait mode
// SPC0 Serial Pin Control Bit 0
// With the MSTR control bit, this bit enables bidirectional pin configurations as shown in Table 3-3.
MODRR=0; //dont redirect anything
// 3.3.3 SPI Baud Rate Register
// Turn on Spi
SPI1CR1 = 0x54;
SPI1CR2 = 0x00; // to enable /SS SPI1CR1 = 0x56; SPI1CR2 =0x10;
SPI1BR = 0x03; // set up Spi baud clock rate div by 16
// SPI1BR = 0x77; // set up Spi baud clock rate div by 2048
SPI1CR1 &= 0xfffd;
SPI1CR1 |= 0x0002; // set spe, new values take effect
// SPSCR = 0x0096; // SPR0, SPMSTR, CPHA, SPE
// SPDSR = 0x0007; // 8-bit size
// SPSCR &= 0xfffd; // clear spe, resets SPI (partial)
// SPSCR |= 0x0002; // set spe, new values take effect
// GPIO_B_PER = 0x00f3; // use GPIOB3 as CS for RTC
// GPIO_B_DDR = 0x000c; // direction is output
//SPSCR
// 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
// MSB: SPRF ERRIE ovrf modf spte modfen spr1 spr0 sprie spmstr cpol cpha spe spite
// 0000 0000 1001 0110
//void reset_spi()
// SPSCR = 0x0096; // SPR0, SPMSTR, CPHA, SPE
// SPDSR = 0x0007; // 8-bit size
// SPSCR &= 0xfffd; // clear spe, resets SPI (partial)
// SPSCR |= 0x0002; // set spe, new values take effect
}
/*******************************************************
* init_DS1305()
******************************************************/
void init_DS1305(){
char grab_key_data=0;
char anykeys[2];
long i;
LCDputs("Initializing ds1305 ");
//use portT pin 0 to control CS of DS1305
PTT = 0; // disble RTC - CS low
PTT = 0x01; // enable RTC - CS high
//burst mode??
wbyte_spi(0x87); // control register write address
rbyte_spi(); // dummy read
wbyte_spi(0x8); // enable alarm1
rbyte_spi();
wbyte_spi(0x8); // enable alarm1
rbyte_spi();
wbyte_spi(0x8); // enable alarm1
rbyte_spi();
wbyte_spi(0x8); // enable alarm1
rbyte_spi();
PTT = 0; // disble RTC - CS low
PTT = 0; // disble RTC - CS low
PTT = 0x01; // enable RTC - CS high
//burst mode??
wbyte_spi(0x8f); // control register write address
rbyte_spi(); // dummy read
wbyte_spi(0x1); // disable write protect enable alarm1
rbyte_spi();
PTT = 0; // disble RTC - CS low
//set trickle chager
PTT = 0; // disble RTC - CS low
PTT = 0x01; // enable RTC - CS high
//burst mode??
wbyte_spi(0x91); // Trickle Charger
rbyte_spi(); // dummy read
wbyte_spi(0xA7); // 1diode 8K ohm
rbyte_spi();
PTT = 0; // disble RTC - CS low
LCDputs(" ");
// R_data=0;
LCDputs("Set Time: Y/N? ");
//print current time here..
//READ CURRENT TIME
PTT = 0x0001; // enable RTC - CS high
wbyte_spi(0); // seconds register read address
rbyte_spi(); // dummy read
wbyte_spi(0);
sec = rbyte_spi(); // read seconds register
wbyte_spi(0);
min = rbyte_spi(); // ditto minutes
wbyte_spi(0);
hr = rbyte_spi(); // and so on
wbyte_spi(0);
dow = rbyte_spi();
wbyte_spi(0);
date = rbyte_spi();
wbyte_spi(0);
mon = rbyte_spi();
wbyte_spi(0);
yr = rbyte_spi();
PTT = 0; // disable RTC - CS low
sec=((sec & 0xF0)>>4)*10+(sec & 0xF);
min=((min & 0xF0)>>4)*10+(min & 0xF);
hr=((hr & 0x30)>>4)*10+(hr & 0xF);
date=((date & 0xF0)>>4)*10+(date & 0xF);
//itoa(date,output);
//LCDputs(output); LCDputs("-Date ");
itoa(hr,output);
LCDputs(output); LCDputs(":");
itoa(min,output);
LCDputs(output); LCDputs(":");
itoa(sec,output);
LCDputs(output);
// check user input
min=0x65;
hr=0x25;
grab_key_data = getkeypad();
//putch(grab_key_data);
if(grab_key_data=='9'){//set time
//prompt for input here:
do{
lcd_cmd(0x01); // clear display and home cursor
for (i=0; i<48000;i++); //wait 2ms
LCDputs("Please Enter Hr :");
anykeys[0]= getkeypad();
LCDputch(anykeys[0]);
anykeys[1]= getkeypad();
LCDputch(anykeys[1]);
hr = twokey_DS1305_num(anykeys);
} while( hr > 0x24);
hr = (hr| 0x40);//set 24 hr mode is bit 6
do{
lcd_cmd(0x01); // clear display and home cursor
for (i=0; i<48000;i++); //wait 2ms
LCDputs("Please Enter Min :");
anykeys[0]= getkeypad();
LCDputch(anykeys[0]);
anykeys[1]= getkeypad();
LCDputch(anykeys[1]);
min = twokey_DS1305_num(anykeys);
}while(min > 0x59);
lcd_cmd(0x01); // clear display and home cursor
for (i=0; i<48000;i++){} //wait 2ms
LCDputs("Setting time..... ");
PTT = 0x001; // enable RTC - CS high
wbyte_spi(0x80); // select seconds register write address
rbyte_spi(); // dummy read
wbyte_spi(0); // seconds register data
rbyte_spi();
wbyte_spi(min); // minutes register
rbyte_spi();
wbyte_spi(hr); // hours register
rbyte_spi();
wbyte_spi(dow); // day of week register
rbyte_spi();
wbyte_spi(date); // date register
rbyte_spi();
wbyte_spi(mon); // month register
rbyte_spi();
wbyte_spi(yr); // year register
rbyte_spi();
PTT = 0; // disble RTC - CS low
}
return;
}
void wbyte_spi( unsigned char wbyte) // ------ write one byte -------
{
while (!(SPI1SR & SPTEF)); // wait for transmitter empty flag
SP1DR = wbyte;
}
unsigned char rbyte_spi(void) // -------- read one byte ----------
{
while (!(SPI1SR & SPIF)); // wait for receiver full flag
return(SP1DR);
}
long Calc_Proj_cost(int Nseg, int i)
{
return (float)Current_cost/(float)(i+1)*(float)(Nseg);
}
void Calc_Curr_cost(int i){
Current_cost += timestamp[i].N_counts_interval*(long)ELEC_COST/1000;
// in cents
}
void write_serial(){
//putch('\n');
//Only Print out data thru Current date, since begin of Month.
Current_cost=0;
// puts("Format: Projected Cost, Current Cost, Month, Day, HH ,MM, SS, N_counts, Rate "); putch('\n');
for(spare_index=0; spare_index < ARRAYSIZE ; spare_index++)
{
Calc_Curr_cost(spare_index); //must be called first
// writing out cost in cents
puti((unsigned long)(Calc_Proj_cost(ARRAYSIZE, spare_index)));// puti(Projected_cost); putascii
puts(", ");
puti((unsigned long)(Current_cost)); //puti(Current_cost); //add put float here
puts(", ");
puti(month);
puts(", ");
puti(timestamp[spare_index].day);
puts(", ");
puti(timestamp[spare_index].hour); // output the current count to serial port
puts(", ");
puti(timestamp[spare_index].min);
puts(", ");
puti(timestamp[spare_index].sec);
puts(", ");
puti(timestamp[spare_index].N_counts_interval);
puts(", ");
puti(ELEC_COST);
putch('\n');
}
}
int twokey_DS1305_num(char keys[2]){
int rval=0;
switch (keys[1]){
case '1': rval=1; break;
case '2': rval=2; break;
case '3': rval=3; break;
case '4': rval=4; break;
case '5': rval=5; break;
case '6': rval=6; break;
case '7': rval=7; break;
case '8': rval=8; break;
case '9': rval=9; break;
case '0': rval=0; break;
default: rval=0; break;
}
switch (keys[0]){
case '1': rval+=0x10; break;
case '2': rval+=0x20; break;
case '3': rval+=0x30; break;
case '4': rval+=0x40; break;
case '5': rval+=0x50; break;
case '6': rval+=0x60; break;
case '7': rval+=0x70; break;
case '8': rval+=0x80; break;
case '9': rval+=0x90; break;
case '0': rval+=0; break;
default: rval+=0; break;
}
return rval;
}
int key_num(char key){
int rval=0;
switch (key){
case '1': rval=1; break;
case '2': rval=2; break;
case '3': rval=3; break;
case '4': rval=4; break;
case '5': rval=5; break;
case '6': rval=6; break;
case '7': rval=7; break;
case '8': rval=8; break;
case '9': rval=9; break;
case '0': rval=0; break;
default: rval=0; break;
}
return rval;
}