Controller Source code

Up Next

//****************************************************************************
// 232I2C.C                                             ©1999 Nick McCurdy 
// Bit-banger program to drive the pins of an 89C2051 as a I2C <> RS232 
// two-way serial interface converter
// Revisions:
// Added code to allow upper or lower case commands 09.13.2001
//
// Stuff to do:
//      Add support for 10 bit extended addressing.
//      Add support for extended response bytes.
//
//****************************************************************************
//#include <reg51.h>
#include <AT892051.H>
#include "handy.h"

//****************************************************************************
//  Globals.
//****************************************************************************
// Character string buffer length.
#define MSGLEN 15

// Counter value for 1 mS interrupt @ 11.059 MHz crystal freq
#define TIMER1MSEC 64613

typedef unsigned char BYTE;

int binval;

BYTE idata rbuf[MSGLEN];
BYTE idata tbuf[MSGLEN];
BYTE idata temp[5];
BYTE idata ticks = 200;
BYTE idata rbin, rbout, tbin, tbout;
BYTE idata I2Address, I2Databyte, I2Command, MSByte, LSByte;
BYTE idata * so;

bit  rfull, tempty, tdone; 

BYTE code ormsg[]={"Over-run\r\n"};
BYTE code olmsg[]={"On-Line\r\n"};
BYTE code bcmsg[]={"Bad Command\r\n"};
BYTE code crlf[]={"\r\n"};
BYTE code negs[]={"-"};
BYTE code half[]={".5"};
BYTE code *ctable[] =  {
  "RP",          /* READ POT   */
  "WP",     /* WRITE POT  */
  "RT",     /* READ TEMP   */
  "WT",     /* WRITE TEMP  */
  ""        /* End of List */
};
#define READPOT  0
#define WRITEPOT 1
#define READTEMP  2
#define WRITETEMP 3
#define NUMCMNDS  5

// I/O Pins
                                                    // Pins for 2051
sbit  TICK = P3 ^ 7;   // 2 mSec Period Sq Wave         11
sbit  SDA  = P3 ^ 4;   // I2C data                       8            
sbit  SCL  = P3 ^ 5;   // I2C clock                      9

#define C2051 1

#ifdef C2051
sbit  RLED = P1 ^ 7;   // READ LED                      19
sbit  WLED = P1 ^ 6;   // WRITE LED                     18
sbit  BLINK= P1 ^ 5;   // BLINKIE LIGHT (Gotta have it) 17
sbit  TLED=  P1 ^ 4;   // THERMOMETER MODE LED          16
#else 
sbit  RLED = P0 ^ 7;   // READ LED                      39
sbit  WLED = P0 ^ 6;   // WRITE LED                     38
sbit  BLINK= P0 ^ 5;   // BLINKIE LIGHT (Gotta have it) 37
sbit  TLED=  P0 ^ 4;   // THERMOMETER MODE LED          36 
#endif 

//****************************************************************************
// Function List
//****************************************************************************
void main(void);
void init(void);

void CodeMessage(BYTE code *);
void DataMessage(BYTE idata *);
void ProcessMessage(void);

void SendSerialData(BYTE idata *);
void WaitforSo(void);
void Reset_msg(void);

void I2Start(void);
void I2Stop(void);
bit  I2Clock(void);
void I2Ack(void); 
bit  I2Nack(void); 
void I2SendByte(BYTE); 
BYTE I2GetByte(void);
 
void waste_time(void);

BYTE Ahtob( BYTE idata*);
void tohex( BYTE b, BYTE idata*);
void scpy( BYTE idata *, BYTE idata *, BYTE);
bit ishex( BYTE );
BYTE slen( BYTE idata *);
BYTE Strpos( BYTE, BYTE idata *);
bit scomp(BYTE idata *, BYTE code *);
void btoa(BYTE, BYTE idata *);
void Reverse(BYTE idata *);
void toup(BYTE idata *);

int ReadLM75(void);

//****************************************************************************
// Main Loop of program.
// Wait for RS232 serial command, parse as needed and execute.
//****************************************************************************
void main(void){
     init();      
     CodeMessage(olmsg);
     while (1){
             while (rfull != TRUE){
             }
             ProcessMessage();                 
          }
}
//****************************************************************************
//  Do something !
//****************************************************************************
void ProcessMessage(void){
   BYTE p;
  
   //scpy(cmnd, rbuf, 0);

   p = 0;
   scpy(temp, rbuf, 2);

   toup(temp);

   while (scomp(temp, ctable[p]) && (p < NUMCMNDS)){    
         p++;
   }
   if (p == NUMCMNDS){
        Reset_msg();
        CodeMessage(bcmsg);
          return;
     }
        
   scpy(temp, &rbuf[3], 2);
   I2Address = Ahtob(temp);
   scpy(temp, &rbuf[6], 2);
   I2Command = Ahtob(temp);
   
   //scpy(temp, cmnd, 2);             ????
   

       
       switch (p){
       case READPOT:          
              RLED = 0;
              WLED = 1;
              TLED = 1;
              
              I2Start();
            I2SendByte(I2Address);
            I2Nack();
            I2SendByte(I2Command);
            I2Nack();            
        I2Databyte = I2GetByte();
        I2Ack();
        I2Stop();
        tohex(I2Databyte, temp);
        DataMessage(temp);   
     CodeMessage(crlf);              
          break; 
                      
   case WRITEPOT:
        RLED = 1;         
        WLED = 0;
        TLED = 1;
        
        I2Start();
            I2SendByte(I2Address);
            I2Nack();
            I2SendByte(I2Command);
            I2Nack();            
          scpy(temp, &rbuf[9], 2);
        I2Databyte = Ahtob(temp);
        I2SendByte(I2Databyte);
        I2Ack();
        I2Stop();
        break;
        
   case READTEMP:
      WLED = 1;          
              RLED = 0;
              TLED = 0;
               
        ReadLM75();        
        break;  
                   
   case WRITETEMP:
        WLED = 0;
        RLED = 1;         
        TLED = 0;
        
        scpy(temp, &rbuf[10], 2);
        I2Databyte = Ahtob(temp);
        I2SendByte(I2Databyte);
        scpy(temp, &rbuf[12], 2);
        I2Databyte = Ahtob(temp);
          I2SendByte(I2Databyte);
          I2Ack();
          I2Stop();
        break;
   default:
        CodeMessage(bcmsg);
        Reset_msg();
        return;
   }
     Reset_msg();
}                 
//****************************************************************************
// Initialize the serial port and other stuff that needs it.
//****************************************************************************
void init(void){
// Serial Poop
ES    = DISABLE;    /* IE.4 - Disable serial port interrupt */
SCON  = SCON_M1;    /* set serial port operating mode       */
PCON  = SMOD_CLR;   /* Clears the SMOD bit                  */
RI    = BIT_CLR;    /* SCON.0 - Clear received data flag    */
TI    = BIT_CLR;    /* SCON.1 - Clear transmit data flag    */
P3    |= 0x03;      /* Set TxD and RxD to Mark State        */

// Timer 1 Poop
ET1   = DISABLE;    /* IE.3 - Disable timer 1 interrupt     */
TR1   = DISABLE;    /* TCON.6 stop timer                    */
TMOD &= 0x0F;       /* clear timer 1                        */
TMOD |= 0x20;       /* Mode 2 for timer 1.                  */
TH1   = BAUD9600;   /* Set baud rate count                  */
//TCON  = BIT0 | BIT6;/* TCON.6&1: start timer 1, edge trig */
TR1   = ENABLE;

// Timer 0 Poop   
TR0   = DISABLE;   // Stop timer 0
TMOD &= 0xF0;      // Clear timer 0
TMOD |= 0x01;      // Mode 1 for timer 0
TH0  = TIMER1MSEC >> 8;
TL0  = TIMER1MSEC & 0x00FF;
ET0   = ENABLE;    // Enable timer 0 interrupts
TR0   = ENABLE;    // Enable timer 0

// Misc Poop
//P0 = 0x55;
tempty = TRUE;
tdone = TRUE;
rfull = 0;
rbout = 0;
rbin  = 0;
tbin  = 0;
tbout = 0;

 // Interrupt Poop
ES    = ENABLE;
EA    = ENABLE;

}
//****************************************************************************
// External Interrupt 0
//****************************************************************************
void irq_ext0(void) interrupt 0{
}
//****************************************************************************
// Timer 0 Interrupt
//****************************************************************************
void irq_timer0(void) interrupt 1{
     TR0  = DISABLE;
     TH0  = TIMER1MSEC >> 8;
     TL0  = TIMER1MSEC & 0x00FF;
     TR0  = ENABLE;
       TICK = ~TICK;
       ticks -=1;
       if (ticks == 0){
            ticks = 200;
            BLINK  = ~BLINK;
       }
}
//****************************************************************************
// External Interrupt 1
//****************************************************************************
void irq_ext1(void) interrupt 2 {
}
//****************************************************************************
// Timer 1 Interrupt
//****************************************************************************
void irq_timer1(void) interrupt 3 {
}
//****************************************************************************
// Serial Port Interrupt 
//****************************************************************************
void serial_interrupt ()  interrupt 4 {
  BYTE data c;
  // Check for receive interrupt.
     if ( RI ){
        CLR_BIT( RI );                      /* clear rcvd data flag */
         c = SBUF;                           /* get character */
         if ( !rfull ) {                     /* is there a msg in buffer?  */
           if ( rbin < MSGLEN ) {           /* is there room?             */
                  rbuf[rbin] = c;
                       if ( isend( rbuf[rbin] ) ){
                         rbuf[rbin] = NUL;       /* overwrite termination */
                              if ( rbin )  {
                                rfull = TRUE;
                              }
                       }
                       else
                         rbin++;
                }
                else {
                       //CodeMessage(ormsg);
                       Reset_msg();               /* buffer overrun */
                       return;
                       //CodeMessage(ormsg);
                }
              }
            }
     if ( TI ) {
        CLR_BIT( TI );  // clear transmit Interrupt flag if there's more data to send, send it.
         if ( so && *so ) {
           SBUF  = *so++;
         }
         else {
           tdone = TRUE;
           so = NUL;
         }
       }
}
//****************************************************************************
// CodeMessage: Copies CODE space data to ram buffer for transmission by SBUF 
//****************************************************************************
void CodeMessage (BYTE code *msg)
{
     tbin = 0;
     while (*msg != 0){
          tbuf[tbin++] = *msg++;
   }
   tbuf[tbin] = NUL;
   if (tdone){
          so = tbuf;
          SendSerialData(so++);
          WaitforSo();
          //Reset_msg();
     }
}
//****************************************************************************
// DataMessage: Copies DATA space data to ram buffer for transmission by SBUF 
//****************************************************************************
void DataMessage (BYTE idata *msg)
{
     tbin = 0;
     while (*msg != 0){
          tbuf[tbin++] = *msg++;
   }
   tbuf[tbin] = NUL;
   if (tdone){
          so = tbuf;
          SendSerialData(so++);
          WaitforSo();
          //Reset_msg();
     }
}
//****************************************************************************
// SendSerialData
//****************************************************************************
void SendSerialData (BYTE idata *msg){
     if (tdone == TRUE)  {
        tdone = FALSE;
        SBUF = *msg;
     }
}
//****************************************************************************
// WaitforSo (Wait for serial output to complete)
//****************************************************************************
void WaitforSo(void) {
BYTE i;
       while ( tdone != TRUE ) {
            for (i=0; i<128;i++);
   }
}
//****************************************************************************
// Clear The Receive Buffer
//****************************************************************************
void Reset_msg(void){
  *rbuf     = NUL;
  rbin      = NUL;      /* no data            */
  rfull     = FALSE;    /* no message pending */
}
//****************************************************************************
// Send Start Condition
//****************************************************************************
void I2Start(void){
     SDA = 1;
     SCL = 1;
     SDA = 0;
     //waste_time();
     SCL = 0;
}
//****************************************************************************
// Send Stop Condition
//****************************************************************************
void I2Stop(void){
     SDA = 0;
     SCL = 1;
     //waste_time();
     SDA = 1;
}
//****************************************************************************
// Clock in one BIT of data
//****************************************************************************
bit I2Clock(void){
     bit sda_value;
//waste_time();
     SCL = 1;
     sda_value = SDA;
     //waste_time();
     SCL = 0;
     //waste_time();
     return(sda_value);
}
//****************************************************************************
// Send Acknowledge Condition
//****************************************************************************
void I2Ack(void){
     SDA = 0;
     I2Clock();
     SDA = 1; 
}
//****************************************************************************
// Send Not-Acknowledge Condition. Sets the SDA high so the receiver can pull
// it low. Added return value to allow ACK poll during EEPOT NV Write 
//****************************************************************************
bit I2Nack(void){
     bit retval;
     SDA = 1;
     retval = I2Clock();
     return retval;
}
//****************************************************************************
// Clock OUT one BYTE of data
//****************************************************************************
void I2SendByte(BYTE b){
     BYTE count;
     for (count = 0; count <= 7; count ++) {
          if ((b & 0x80) == 0 )
               SDA = 0;
          else
               SDA = 1;
          b = b << 1;
          I2Clock();
     }
}
//****************************************************************************
// Clock IN one BYTE of data
//****************************************************************************
BYTE I2GetByte(void){
     BYTE count, d;
     for (count = 0; count <= 7; count++) {
          SDA = 1;
          d = d << 1;
          d |= (BYTE) I2Clock();
     }
     return (d);
}
/******************************************************
**  Procedure:  tohex ( BYTE, BYTE * )
**
**  Description:
**  -----------
**  Converts the byte into a two digit ASCII hex string
**  in buffer 'p'.
**  
******************************************************/
void tohex( BYTE b, BYTE idata *p )
{
  /* first digit */
  p[0] = b >> 4;
  if ( p[0] < 10 )
    p[0] += 0x30;             /* 0 - 9 */
  else
    p[0] = (p[0] - 9) | 0x40; /* A - F */

  /* second digit */
  p[1] = b & 0x0F;
  if( p[1] < 10 )
    p[1] += 0x30;             /* 0 - 9 */
  else
    p[1] = (p[1] - 9) | 0x40; /* A - F */
  p[2] = NUL;     /* terminate string */
}

/******************************************************
**  Procedure:  Ahtob ( BYTE * )
**
**  Description:
**  -----------
**  Converts a two digit ASCII Hex string in buffer 'p'
**  to a byte, and returns that byte.
**  
******************************************************/
BYTE Ahtob( BYTE idata *p )
{
  BYTE data b;
  /* Most Significant digit */
  if ( p[0] > 64 )
    b = p[0] - 55;    /* Convert A - F to binary  */
  else
    b = p[0] - 0x30;  /* Convert 0 - 9 to binary  */
  b <<= 4;

  /* Least Significant digit */
  if ( p[1] > 64 )
    b |= p[1] - 55;   /* Convert A - F to binary  */
  else
    b |= p[1] - 0x30; /* Convert 0 - 9 to binary  */
  return(b);
}
/******************************************************
**  Procedure:  void scpy( BYTE *, BYTE * )
**
**  Description:
**  -----------
**  Copies string s2 to location s1, up to and including
**  the NUL character.
**
******************************************************/
void scpy( BYTE idata *s1, BYTE idata *s2, BYTE L )
{
     BYTE i;
     
     if (L == 0){     
            do {
              *s1++ = *s2;
            }
            while ( *s2++ );
       }
       else {
            for (i = 0; i<L; i++){
                 *s1++ = *s2++;
            }
            *s1 = NUL;
       }
}
/******************************************************
**  Procedure:  void slen( BYTE * )
**
**  Description:
**  -----------
**  Counts the number of bytes in string 's', minus 
**  the NUL.
**  Stops at the first NUL character.
**
******************************************************/
BYTE slen( BYTE idata *s )
{
  BYTE data c = 0;
  while ( s[c] ) {
    c++;
  }
  return( c );
}
/******************************************************
**  Procedure:  ishex ( BYTE )
**
**  Description:
**  -----------
**  Returns TRUE if 'c' is an ASCII hex character:
**  0 - 9, A - F, or a - f.
**  
*****************************************************/
bit ishex( BYTE c )
{
  if ( isnum(c) ) 
    return( TRUE );               /* 0 - 9 */
  if ( (c > 0x40) && (c < 0x47) ) /* A - F */
    return( TRUE );
  if ( (c > 0x60) && (c < 0x67) ) /* a - f */
    return( TRUE );
  return( FALSE );
}
/******************************************************
**  Procedure:  Strpos ( BYTE, BYTE * )
**
**  Description:
**  -----------
**  Search string 'p' for the first occurance of 'b'.
**  Returns the index of 'b' in the string, or -1 if
**  not found.
**  
******************************************************/
BYTE Strpos( BYTE b, BYTE idata *p )
{
  BYTE i = 0;
  while ( p[i] != b ) {
    if ( isend( p[i] ) )
      return( -1 );
    i++;
  }
  return( i );
}
//****************************************************************************
// Compares two strings returns a 0 for match and 1 for no match.
//****************************************************************************
bit scomp(BYTE idata *p1, BYTE code *p2){
     while( *p1 == *p2){
        if (*p1 == NUL) return 0;
          p1++, p2++;
     }
     return 1;
}     
/******************************************************
**  Procedure:  void btoa( BYTE, BYTE * )
**
**  Description:
**  -----------
**  Converts byte 'n' to an ASCII string in location 's'.
**  This only works for unsigned numbers 0 - 255.
**
******************************************************/
void btoa( BYTE n, BYTE idata *s )
{
  BYTE data i = 0;

  do {  /* generate digits in reverse order */
    s[i++] = n % 10 + 0x30;
  }
  while( (n /= 10) > 0 );
  s[i] = NUL;

  /* reverse the digit order */
  Reverse( s );
}
/******************************************************
**  Procedure:  void Reverse( BYTE data * )
**
**  Description:
**  -----------
**  Reversed the order of the characters in string 's'.
**
******************************************************/
void Reverse( BYTE idata *s )
{
  BYTE data c, i, j;

  j = slen( s ) - 1;

  for (i = 0 ; i < j; i++, j--) {
    c = s[i];
    s[i] = s[j];
    s[j] = c;
  }
}
//****************************************************************************
// Reads and returns the value of the selected register in the addressed LM75
//****************************************************************************
int ReadLM75(void){

              I2Address << 1;
              I2Address &= 0xFE;
              I2Address |= 0x90;
              I2Start();
              I2SendByte(I2Address);
              I2Ack();
              
              I2SendByte(I2Command);
              I2Ack();
              I2Start();
              I2Address |= 0x01;
              I2SendByte(I2Address);
              I2Ack();
              
              MSByte = I2GetByte();
              I2Nack();
              if (I2Command != 1){
                   LSByte = I2GetByte();
                   I2Nack();
              }
              else{
                   LSByte = MSByte;
                   MSByte = 0;
              }
              I2Stop();
                           
        binval = MSByte;
        binval = binval << 8;
        binval = binval + LSByte;
         binval = binval >> 7;
        MSByte = binval >> 8;
        LSByte = binval & 0xFF;
        
        if (MSByte & 1){
             CodeMessage(negs);
             LSByte = ~LSByte;
             LSByte++;
        }
        
            MSByte = LSByte; // Save the LSB  
        LSByte /= 2;
        btoa(LSByte, temp);                
        DataMessage(temp);
        if (MSByte & 1){
             CodeMessage(half);
        }
        CodeMessage(crlf);
      return binval;
}
//****************************************************************************
// Converts characters to upper case
//****************************************************************************
void toup(BYTE idata *r)
{
BYTE i;
     for (i=0; i<2; i++){
          r[i] = r[i] & 0x5F;
          //DataMessage(r);
          
     }