#include /****************************Function Prototypes*******************************************************************/ void timer0 (void); // implements a approx 100µS interrupt void SERIAL(void); // implements the SMS message receive and Parse routine /*************************************Patterns Used Kept in code Memory as LUTs************************************/ code char HEADER[]="Waiting for a message From "; // Until a message is actually received this message is played code char NoMaster[16]="\" ANY NUMBER \""; //if a new or none EEPROM is installed then the master will be this code char *PATTERN="+CMT: "; // This is the pattern that is given by the SIM300Z modem on a new SMS // Following bytes are output by the µC for selecting an individual display column code char BANK[40]={1,1,1,1, 1, 1, 1, 1,2,2,2,2, 2, 2, 2, 2,4,4,4,4, 4, 4, 4, 4,8,8,8,8, 8, 8, 8, 8,16,16,16,16,16,16,16, 16}; //-|--------------------|--------------------|--------------------|--------------------|------------------------| code char COL[40]= {1,2,4,8,16,32,64,128,1,2,4,8,16,32,64,128,1,2,4,8,16,32,64,128,1,2,4,8,16,32,64,128, 1, 2, 4, 8,16,32,64,128}; //-|--------------------|--------------------|--------------------|--------------------|------------------------| /***********************************************Externals**********************************************************/ extern code char FONT[256][7]; // Refers to the look up table of fonts. It is in the LUT_1_ON.c file extern void ERASE_WRITE (void); // Function in 93C46B.C to erase/write a word to EEPROM extern void ROM(void); // Function in 93C46B.C to give commands and Read from EEPROM extern void Init_ROM (void); // Function in 93C46B.C to initialize EEPROM extern char ROM_OPAD; // in 93C46B.C EEPROM opcode+address byte extern int ROM_WRD; // in 93C46B.C EEPROM data word buffer for reads and writes sbit ROM_DO = P3^2; // P3.2 EEPROM CS pin(4) of 93C46B is connected here | sbit ROM_DI = P3^3; // p3.3 EEPROM DI pin(3) of 93C46B is connected here | sbit ROM_CK = P3^4; // P3.4 EEPROM DO pin(2) of 93C46B is connected here | sbit ROM_CS = P3^5; // P3.5 EEPROM CK pin(1) of 93C46B is connected here /******************************Variables for Serial Receive / Parse Routine*****************************************/ unsigned char MATCHED; // Keeps number of bytes that has been yet matched unsigned char LAST_RXD; // Keeps last received byte, implemented to check for end of string unsigned char MSG_PART; // Keeps track of receiver state unsigned char i; // Loop Counter /******************************Variables for Display Screen Purpose************************************************/ unsigned char IN_MESSAGE; // keeps record of byte number of message being displayed char OFFSET; // keeps track of column offset in current displayed character unsigned int HOLD; // keeps dead wait time for holding a column on screen char NEXT; // keeps next column's data that will enter from left in the screeen char LAST_COL=40; // valid display's last column is 40 unsigned char DISP_RAM[40]=0; // RAM for Display /********************************************Memory Buffers*********************************************************/ idata char MESSAGE[108] = "WWW.COM";// Message Buffer 108 Byte internal RAM char MASTER[16]="\" ANY NUMBER \"";// The Default Master telephone number is none so any one can send a message // 15 characters a phone number enclosed in quotation marks the sixteenth // is a string terminator NULL /*******************************************Misc Variables**********************************************************/ bit PAUSED; // Flag to Pause the Display bit DEFAULTED; // Flag to Mark that defaults were Loaded. bit UPDATING_MASTER=0; // Flag to Mark thet a new phone number is being received bit MASTER_NEW=0; // Flag to Mark that full new Master has been received sbit DEFAULTS=P3^7; // Port pin to load defaults /*********************************Function to initialize different settings in the AT89C52**************************/ void init(void) { Init_ROM(); // Initialize EEPROM; if (!DEFAULTS) // User wants defaults? { for (i=1;i<14;i++) // Do it for 13 bytes { ROM_WRD=MASTER[i]; // Copy Master number into EEPROM input word ROM_OPAD=0x040+i; // Make rom opcode to write on location i ERASE_WRITE (); // Call Erase_write() to complete the write operation } DEFAULTED=1; // permit all to send a message (implemented to set a master number first time) } else { for (i=1;i<14;i++) // Repeat for 13 bytes " delibrately 0th location has been skipped because // it always contains quotation mark i.e. " { ROM_OPAD=0x080+i; // Make Rom opcode to Read on location i ROM(); // Call ROM() to cause the read if (ROM_WRD<'0' || ROM_WRD>'9') // a non number was read from the EEPROM? { for (i=0;i<15;i++) { MASTER[i]=NoMaster[i]; } DEFAULTED=1; // Mark the flag so that any number can send a message break; // break the loop of reading EEPROM } else MASTER[i]=ROM_WRD; // Copy Master number digit from EEPROM input word } } for(i=0;i'9')// a non number? so A new EEPROmM may have been Connected. // { // DEFAULTED=1; // permit all to send a message (implemented to set a master number first time) // break; // } // } P0=0x000; // Make display Blank P2=0; // unselect all column Banks P1=0; // unselect all columns TMOD=0x022; // TIMER1 IN MODE 2 ,TIMER0 IN MODE 2 TH1=-3; // 9600 baud @11.0592MHz TH0=-92; // Divide internal clock on 92 (11.0592e6/12)/92~=100µS SCON = 0x50; // Setup serial port control register // REN=1; // Enable Receiver IE=0x092; // Enable Timer0 and serial Interrupts IP=0x010; // Serial is the highest priority interrupt TR0=1; // Start the clock TR1=1; // Start the serial port clock MATCHED=0; // new message pattern not matched yet at the receiver MSG_PART=0; // Keeps track that in which part of message receive we are IN_MESSAGE=0; // We are at first character of the message OFFSET=0; // We are at first column of current character// NEXT=0x000; // NEXT Line entering from left will be blank } /***************************Function that displays RAM contents on the actual LEDS****************************/ void DISPLAY(char REPEAT) // display RAM data @ 31.25 FPS { char i; // Loop Counter while(REPEAT) // Repeating? { for(i=0;i<40;i++) // Do it for 40 times { P0=0x000; // Blank the Display TL0=-100; // Reset Timer to 100µS HOLD=1; // Set Hold Time to ~100µs; while(HOLD); // Let the Hold Time Expire P2=BANK[i]; // Select column bank P1=COL[i]; // Select column in current bank P0=DISP_RAM[i]; // Copy RAM data of current column onto display TL0=-100; // Reset Timer to 100µS HOLD=4; // Set Hold Time to ~400µs; while(HOLD); // Let the Hold Time Expire } REPEAT--; // Decrement repeat count } P2=0x000; // Blank the Display P0=0x000; // ----------------- TL0=-100; // Reset Timer to 100µS HOLD=10; // Set Hold Time to ~1000µs; } /************************Function that makes the display shift to left by one column*******************************/ void LSHIFT (void) { char i; // Local Loop Counter for(i=0;i<39;i++) // loop for 39 columns { DISP_RAM[i]=DISP_RAM[i+1]; //copy next column's data into current column } DISP_RAM[39]=NEXT; // Copy last column from the Next buffer if(!MESSAGE[IN_MESSAGE]) // Null Found at IN_Mesage Pointer? { if (LAST_COL<2) // Last Blanked column was Col1? { IN_MESSAGE=0; // Restart message display from first character OFFSET=0; // Restart message display from first column } else // Last blanked column was more than 1? { NEXT=0x00; // Next Column is to be Blank LAST_COL--; // Last Blanked Column Count has decreased by 1 } } else if (FONT[MESSAGE[IN_MESSAGE]][OFFSET]==0x000) // Current character's last column was displayed? { IN_MESSAGE++; // point to next character in message OFFSET=0; // The new character is to start from column 1 NEXT=0x000; // Blank column between two characters } else // neither end of messsage nor end of character? { NEXT= FONT[MESSAGE[IN_MESSAGE]][OFFSET]; // currently pointed column will go on display next LAST_COL=40; // data has been entered at col 40 OFFSET++; // next time we shall try next column of current character } } /******************************Function that governs the main algorithm*********************************************/ void main (void) { unsigned char j; init(); while(1) { DISPLAY(2); // Display current RAM 6 Times if (!PAUSED)LSHIFT(); // LShift the Display by one column if (MASTER_NEW) // A new phone number was designated as master? { for (j=1;j<14;j++) // Repeat for 13 bytes { ROM_OPAD=0x0C0+j; // Make EEPROM command as delete at word j ERASE_WRITE (); // Execute the erase command ROM_WRD=MASTER[j]; // Copy new data byte to rom i/o word ROM_OPAD=0x040+j; // Make Write command at current address ERASE_WRITE (); // Execute the Word write command } MASTER_NEW=0; // Unmark the master new flag for(i=0;i0x030&&SBUF<0x03A)||(SBUF=='+'&&MATCHED==2)) // A Valid Number? { MASTER[MATCHED-1]=SBUF; // Save it in the Master number just after " mark if (MATCHED==14) // Full master received? because { UPDATING_MASTER=0; // Updating Master has finished MASTER_NEW=1; // Mark flag that Master is new so it may be stored in EEPROM DEFAULTED=0; // Now we have a new master number. goto RELEASE; // Release the display and show new master number } } else { goto RELEASE; // Release the display master will be updated in EEPROM } } break; //-------------------Resetting Receiver Status to wait for a new message-----------------------// RELEASE: for(i=0;i<40;i++)DISP_RAM[i]=0; // Display becomes blank IN_MESSAGE=0; // Start the Display from character 1 OFFSET=0; // Start it from start PAUSED=0; // Unpause Display NEXT=0; // Next column is surly blank DEFAULT: // Let the new message scroll default: MSG_PART=0; // Waiting for a new message if(SBUF=='+')MATCHED=1; // Current character is '+' so it may be start of "+CMT: " else MATCHED=0; // Nothing usable recceived yet } LAST_RXD=SBUF; // Keep current byte for comparison with next byte } else { TI=0; // We do not transmit anything } }