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;

}