bam_eep.c



/****************************************************************************/
/*     MODULE: bam_eep.c                                                    */
/*   FUNCTION: EEPROM Programming routines.                                 */
/*  PROCESSOR: 8xC196KC                                                     */
/*   CONTAINS:																*/
/*    HISTORY:  4-3-96 L.R. Erickson - Original								*/
/****************************************************************************/

#define SRC_BAM_EEP

#include "jkc_defs.h"
#include "jkc_sfrs.h"
#include "jkc_extr.h"
#include "jkc_func.h"

#include "bam_loop.h"
#include "bam_main.h"
#include "bam_defs.h"

#include "bam_ser.h"
#include "bam_comm.h"
#include "bam_eep.h"

#pragma interrupt(eep_transmit=24)
#pragma interrupt(eep_receive=25)


/* File Global Vars */

EEP_TX_struct *tx_data_ptr ;
EEP_RX_struct *rx_data_ptr ;



/********************************************************/
/*    ROUTINE: eep_main 								*/
/*   FUNCTION:The EEPROM programming routine.           */
/*                                                      */
/********************************************************/
void 
eep_main(void)
{

    EEP_TX_struct tx_data ;
    EEP_RX_struct rx_data ;

    tx_data_ptr = &tx_data ;
    rx_data_ptr = &rx_data ;

    init_eep_data() ;

        // Wait for startup time out or char.
    while(!eep_chk_ch_bit(fixed_status,FIXED_STAT_GOON)) {
        // char received?
      if(rx_data.head_index != rx_data.tail_index) {
        // yes - reset time out.
        disable() ;
        fixed_num_overflows = 0 ;
        enable() ;
        // and process char.
        process_eep_char() ;  
      } 
        // Check for TX hung.
      if(tx_data.tx_busy && (fixed_num_overflows > 500)) {
        // If hung let WDT time out.
        disable() ;
        while(1) ;
      }
    } // end while

}

/********* end of eep_main *****************************/


/********************************************************/
/*    ROUTINE: eep_transmit								*/
/*   FUNCTION:The EEPROM programming transmit interrupt */
/*             handler.                                 */
/********************************************************/
void 
eep_transmit(void)
{
    unsigned char local_stat ;
    
	//
	// Stack pointer check: If bad, loop till wdt reset
	//
	while ( (sp>STACK_TOP) || (sp<STACK_BOT) );

      // Not sure if this is necessary, but will
      // read status to make sure interrupt is cleared.
      // Also clears RB8.
    local_stat = sp_stat ;

      // Char to send?
    if(tx_data_ptr->tail_index == tx_data_ptr->head_index) {
        tx_data_ptr->tx_busy = FALSE ;
        return ;
         }

      // Fall thru means yes send char.
    sbuf = tx_data_ptr->tx_buf[tx_data_ptr->tail_index] ;
    tx_data_ptr->tail_index++ ;

}

/************** end of eep_transmit *********************/

/********************************************************/
/*    ROUTINE: eep_receive								*/
/*   FUNCTION: The EEPROM programming receive           */
/*              interrupt handler.                      */
/********************************************************/
void
eep_receive(void)
{
	unsigned char    rx_char, tst_index, local_stat ;
    
	//
	// Stack pointer check: If bad, loop till wdt reset
	//
	while ( (sp>STACK_TOP) || (sp<STACK_BOT) );

        // Read the uart.  This also clears the
        // interrupt.
    local_stat = sp_stat & (RB8_BIT | FE_BIT | OE_BIT) ;
    rx_char = sbuf ;

        // Check 9th bit
    if(eep_chk_ch_bit(local_stat,RB8_BIT)) {
            // Our address?
      if(rx_char == mc_address) {
           // Switch to receive all.
        serial_mode(3) ; }
      else {
           // Put in cmd listen mode.
        serial_mode(2) ;
        return ; }  
      } // End if RB8

        // Fall thru means we have a char to process.
        // Higher level process will handle errors.
    rx_data_ptr->rx_stat[rx_data_ptr->head_index] = local_stat ;
    rx_data_ptr->rx_buf[rx_data_ptr->head_index] = rx_char ;

        // Setup for next.
    if(++rx_data_ptr->head_index >= EEP_RX_BUF_SIZE)
             rx_data_ptr->head_index = 0 ;

        // check for buffer overflow
    if((rx_data_ptr->head_index == rx_data_ptr->tail_index) ||
        (rx_data_ptr->rx_crash > 0)) rx_data_ptr->rx_crash ++ ;
    else rx_data_ptr->rx_crash = 0 ;

}

/**************** end of eep_receive *******************/

/********************************************************/
/*    ROUTINE: init_eep_data 							*/
/*   FUNCTION:Initialize the EEPROM programming data    */
/*             structures.                              */
/********************************************************/
void 
init_eep_data(void)
{

    tx_data_ptr->tx_busy = FALSE ;

    rx_data_ptr->head_index = 0 ;
    rx_data_ptr->tail_index = 0 ;
    rx_data_ptr->rx_crash = 0 ;
    rx_data_ptr->rx_proc_state = EEP_WT_CMD_STATE ;

}

/**************** end of init_eep_data *****************/

/********************************************************/
/*    ROUTINE: process_eep_char							*/
/*   FUNCTION:Process the EEPROM programming received   */
/*             data                                     */
/********************************************************/
void 
process_eep_char(void)
{

unsigned char proc_byte, err_flags ;

        // Check rx buf integrity.
    if(rx_data_ptr->rx_crash > 1) {
          // advise
        send_eep_msg(EEP_BUF_ERR) ;
          // flush buf & reset rx
        disable() ;
        rx_data_ptr->head_index = 0 ;
        rx_data_ptr->tail_index = 0 ;
        rx_data_ptr->rx_crash = 0 ;
        enable() ;        
        rx_data_ptr->rx_proc_state = EEP_WT_MSG_STATE ;
        return ;
      }

        // get byte and status from buffer
    proc_byte = rx_data_ptr->rx_stat[rx_data_ptr->tail_index] ;
    err_flags = rx_data_ptr->rx_buf[rx_data_ptr->tail_index] ;


       // Setup for next.
    if(++rx_data_ptr->tail_index >= EEP_RX_BUF_SIZE)
             rx_data_ptr->tail_index = 0 ;

  /************  Start of RX error checking ***************/  

        // Check for cmd state error.
    if((eep_chk_ch_bit(err_flags,RB8_BIT)) &&
        (rx_data_ptr->rx_proc_state != EEP_WT_MSG_STATE)) {
          // advise.
        send_eep_msg(EEP_CMD_STATE_ERR) ;
          // and go ahead and process.
        rx_data_ptr->rx_proc_state = EEP_WT_MSG_STATE ;
        }

        // Check WT_MSG_STATE errors.
    if(rx_data_ptr->rx_proc_state == EEP_WT_MSG_STATE) {
           // Check 9th bit & errors
        if((!eep_chk_ch_bit(err_flags,RB8_BIT)) ||
         eep_chk_ch_bit(err_flags,FE_BIT) || eep_chk_ch_bit(err_flags,OE_BIT)) {
            // going to ignore.  If not cmd error already reported.
            // Replying to wrong address would screw up commo lines.
          return ; }
      }
    else if(eep_chk_ch_bit(err_flags,FE_BIT)) {
          // advise.
        send_eep_msg(EEP_FE_ERR) ;
          // abort processing.
        rx_data_ptr->rx_proc_state = EEP_WT_MSG_STATE ;
        return ;
        }
    else if(eep_chk_ch_bit(err_flags,OE_BIT)) {
          // advise.
        send_eep_msg(EEP_OE_ERR) ;
          // abort processing.
        rx_data_ptr->rx_proc_state = EEP_WT_MSG_STATE ;
        return ;
        }

 

  /*************** Start of processing state machine. *******/
    

    switch(rx_data_ptr->rx_proc_state)
    {
    case EEP_WT_MSG_STATE:

          // RX isr has checked address.
        rx_data_ptr->rx_proc_chksum = proc_byte ;
        rx_data_ptr->rx_proc_state = EEP_WT_CMD_STATE ;
        break ;

    case EEP_WT_CMD_STATE:
        rx_data_ptr->rx_proc_cmd = proc_byte ;
        rx_data_ptr->rx_proc_chksum += proc_byte ;
        switch(rx_data_ptr->rx_proc_cmd)
        {
          case EEP_PROG_CMD:   
          rx_data_ptr->rx_proc_state = EEP_WT_CNT_STATE ;
          break;

          default:
            send_eep_msg(EEP_UNK_CMD_ERR) ;
            rx_data_ptr->rx_proc_state = EEP_WT_MSG_STATE ;
            return ;
        }
        break ;

    case EEP_WT_CNT_STATE:
        if(proc_byte > MAX_PROG_CHARS) {
            send_eep_msg(EEP_MAX_CNT_ERR) ;
            rx_data_ptr->rx_proc_state = EEP_WT_MSG_STATE ;
            return ;
        }
        rx_data_ptr->rx_proc_cnt = proc_byte ;
        rx_data_ptr->rx_proc_chksum += proc_byte ;
        rx_data_ptr->rx_proc_state = EEP_WT_HI_ADD_STATE ;
        break ;

    case EEP_WT_HI_ADD_STATE:
        rx_data_ptr->rx_proc_ld_add = (unsigned int) proc_byte ;
        rx_data_ptr->rx_proc_ld_add = 
                (rx_data_ptr->rx_proc_ld_add << 8) ;
        rx_data_ptr->rx_proc_chksum += proc_byte ;
        rx_data_ptr->rx_proc_state = EEP_WT_LO_ADD_STATE ;
        break ;

    case EEP_WT_LO_ADD_STATE:
        rx_data_ptr->rx_proc_ld_add |= (unsigned int) proc_byte ;
        rx_data_ptr->rx_proc_chksum += proc_byte ;
        rx_data_ptr->rx_data_cnt = 0 ;
        rx_data_ptr->rx_proc_state = EEP_WT_DATA_STATE ;
        break ;

    case EEP_WT_DATA_STATE:
        rx_data_ptr->rx_prog_chars[rx_data_ptr->rx_data_cnt]
                        = proc_byte ;
        rx_data_ptr->rx_proc_chksum += proc_byte ;
        if(++rx_data_ptr->rx_data_cnt >=
                rx_data_ptr->rx_data_cnt)
            rx_data_ptr->rx_proc_state = EEP_WT_CHK_STATE ;
        break ;

    case EEP_WT_CHK_STATE:
        rx_data_ptr->rx_proc_chksum += proc_byte ;
        if(rx_data_ptr->rx_proc_chksum != 0) {
            send_eep_msg(EEP_CHK_SUM_ERR) ;
            rx_data_ptr->rx_proc_state = EEP_WT_MSG_STATE ;
            return ;
        }
        send_eep_msg(EEP_PROG_CMD_ACK) ;
            // Go write program.
        if(write_eeprom()) send_eep_msg(EEP_PROG_CMD_DONE) ;
        else send_eep_msg(EEP_PROG_CMD_FAIL) ;

        rx_data_ptr->rx_proc_state = EEP_WT_MSG_STATE ;
        break ;

    default:
        // Something seriously wrong if we get here.
        // We'll let the WDT time out.
        disable() ;
        while(1) ;

    } // end switch rx_proc_state.


}

/**************** end of process_eep_char *****************/

/********************************************************/
/*    ROUTINE: send_eep_msg  							*/
/*   FUNCTION: send a msg to the master computer.       */
/*                                                      */
/********************************************************/
void 
send_eep_msg(int msg_num)
{

unsigned char chk_sum ;

        // Check for TX hung.
    while(tx_data_ptr->tx_busy) {
      if(fixed_num_overflows > 500) {
        // If hung let WDT time out.
        disable() ;
        while(1) ; }
      }

        //Initialize
    tx_data_ptr->head_index = 0 ;
    tx_data_ptr->tail_index = 0 ;
    chk_sum = mc_address ;
        // Load msg bytes.
    chk_sum += EEP_REPLY ;
    tx_data_ptr->tx_buf[tx_data_ptr->head_index] = EEP_REPLY ;
    tx_data_ptr->head_index++ ;
    chk_sum += msg_num ;
    tx_data_ptr->tx_buf[tx_data_ptr->head_index] = msg_num ;
    tx_data_ptr->head_index++ ;
    chk_sum += 0 ;
    tx_data_ptr->tx_buf[tx_data_ptr->head_index] = 0 ;
    tx_data_ptr->head_index++ ;
    chk_sum += 0 ;
    tx_data_ptr->tx_buf[tx_data_ptr->head_index] = 0 ;
    tx_data_ptr->head_index++ ;
    chk_sum = ~chk_sum ;
    chk_sum++ ;
    tx_data_ptr->tx_buf[tx_data_ptr->head_index] = chk_sum ;
    tx_data_ptr->head_index++ ;

        // Start UART
    tx_data_ptr->tx_busy = TRUE ;
    _set_SFRbit_(sp_con, SET_BIT_8) ;
    sbuf = mc_address ;

       // All done. Ints will take care of rest.

}

/**************** end of send_eep_msg *****************/


/********************************************************/
/*    ROUTINE: eep_chk_ch_bit  							*/
/*   FUNCTION: nondestructive char bit set check.       */
/*                                                      */
/********************************************************/
unsigned char 
eep_chk_ch_bit(unsigned char tst_byte, unsigned char bit_num )
{
  return(checkbit(tst_byte, bit_num)) ;
}

/**************** end of eep_chk_ch_bit *****************/


/********************************************************/
/*    ROUTINE: write_eeprom  							*/
/*   FUNCTION: write the chars to the eeprom.           */
/*                                                      */
/********************************************************/
unsigned char 
write_eeprom(void)
{

volatile unsigned char *wr_prot_add_1 
   = (unsigned char *) (0x5555 + 0x8fff) ;
volatile unsigned char *wr_prot_add_2 
   = (unsigned char *) (0x2aaa + 0x8fff) ;
              
unsigned char write_offset ;

    // Do write protect.
//    *wr_prot_add_1 = 0xaa ;
//    *wr_prot_add_2 = 0x55 ;
//    *wr_prot_add_1 = 0xa0 ;    

    write_offset = 0 ;
    while(write_offset < rx_data_ptr->rx_data_cnt) 
    {
    *(char *)(rx_data_ptr->rx_proc_ld_add + write_offset)
             = rx_data_ptr->rx_prog_chars[write_offset] ;
    write_offset++ ;
    }

      // Index back to last byte.
    write_offset-- ;
      // Wait till EEPROM done.
    while(*(char *)(rx_data_ptr->rx_proc_ld_add + write_offset)
        != rx_data_ptr->rx_prog_chars[write_offset]) {
        if(fixed_num_overflows > 100) return(FALSE) ;
        }

  return(TRUE) ;
}

/**************** end of write_eeprom *********************/