; 93C57 EEPROM WRITER ; Read and Write data from/to 93C57 serial EEPROM ; Modified from 59C11 programmer Ver.2.2. ; Supports 16 bit mode ONLY. While 8 bit routines are there ; they are ignored. ; Adjust rate_9600, ee_delay and delay_1msec if Xtal freq. ; is other than 3.58MHz. ; ; Copyright 2001 Tickets, All rights reserved ; ; NOTE: This code is written in Paralax SPASM format. ; device pic16f84,hs_osc,wdt_off,protect_off,pwrt_on ;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; DEFINITIONS ;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; Version version_major = '0' ; Major version version_minor = '2' ; Minor version ; I/O Ports ; RS232C Ports serial_rxd = PortA.0 ; RS232C RXD (Output) serial_txd = PortB.0 ; TXD (Input) rate_9600 = 28 ; 9600bps rate_half = rate_9600/2 ; Half bit ; EEPROM 93C57 ee_do = PortB.1 ; DO (Input) ee_di = PortA.1 ; DI (Output) ee_clk = PortA.2 ; CLK (Output) ee_cs = PortA.3 ; CS (Output) ee_rdy = PortB.2 ; RDY/BSY (Input) H=Ready ee_mode = PortB.3 ; 93C57 mode (Input) L=8bit ; H=16bit ; Command construction(16bit) ; A: Address(A6-A0) ; X: Don't care ; READ 10AAAAAAA ; WRITE 01AAAAAAA ; EWEN 0011XXXXX ; EWDS 0000XXXXX ee_rdcmd = 11000000b ; Left 3 bits including start bit ee_wrcmd = 10100000b ; starts from left ee_ewen = 10000000b ; EEPROM write enable dummy_ewen = 11111111b ; First 2bits are part of EWEN command ee_ewds = 10000000b ; EEPROM write disable dummy_ewds = 00000000b ; First 2bits are part of EWDS command ee_cmdcntr = 3 ; 3bits for command and start bit ; EWEN/EWDS requires address field ; as a part of command (FFh/00h) ee_adrcntr8 = 8 ; 8bits for address (byte config.) ee_adrcntr16 = 7 ; 7bits for address (double byte) ee_datacntr = 8 ; 8bits for data ee_maxadr8 = 00h ; Address limit for 8bit (100h) ee_maxadr16 = 80h ; Address limit for 16bit ; ASCII Code code_cr = 0Dh ; CR code code_lf = 0Ah ; LF code_esc = 1Bh ; ESC code_space = 20h ; Space ;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ org 0ch ; Top of available RAM ; RS-232C mode ds 1 ; EEPROM mode 0=8bit NZ=16bit bit_cntr ds 1 ; Bit counter xmt_byte ds 1 ; Transmit data rcv_byte ds 1 ; Received data delay_cntr ds 1 ; RS232C delay delay_cnt2 ds 1 ; delay_cnt3 ds 1 ; msg_cntr ds 1 ; Message counter conv_byte ds 1 ; Byte to be converted hex_data ds 1 ; HEX input buffer first_byte ds 1 ; 0=first byte temp ds 1 ; Temporary buffer str_pointer ds 1 ; Pointer for string data ; 93C57 ee_address ds 1 ; Address ee_adrcntr ds 1 ; ee_maxadr ds 1 ; Address limit 40h or 80h ee_wdatah ds 1 ; Write data High byte ee_wdatal ds 1 ; Write data Low byte ee_rdatah ds 1 ; Read data High byte ee_rdatal ds 1 ; Read data Low byte ee_cntr ds 1 ; EEPROM data bit counter ee_buff ds 1 ; Buffer quit_flag ds 1 ; Quit Process if non zero error_flag ds 1 ; 0 if no error skip_flag ds 1 ; Skip process if non zero ignore_flag ds 1 ; Ignore input if non zero id '9357' ; Product ID org 0 start init mov intcon,#00000000b ;Interrupt control ; Disables all Interrupt mov option,#00000000b ;Option register ; 7 Port-B pull up (L:ON) ; 6 Interrupt trigger (L:H to L) ; 5 RTCC source (L:Clock) ; 4 RTCC trigger (L:H to L) ; 3 Prescaler (L:RTCC) ;2-0 Prescaler ratio (0=1:1) mov !ra,#11110000b ;A-Port ; RA0 RXD (Output) ; RA1 93C57 DI ; RA2 93C57 CLK (L to H) ; RA3 93C57 CS (Active H) mov !rb,#11111111b ;B-Port ; RB0 TXD (Input) ; RB1 93C57 DO ; RB2 93C57 RDY (Active H) ; RB3 93C57 ORG (L=8bit) setb serial_rxd ; Init serial output clrb ee_cs ; Disable 93C57 call delay_1msec call disable_command ; Dummy command for init. call send_address ; dummy address clrb ee_cs ; mov ee_adrcntr,#ee_adrcntr8 ; Set for 8bit ; mov ee_maxadr,#ee_maxadr8 clr mode ; Check mode input jnb ee_mode,:eight ; Mode input is Low (8bit mode) inc mode ; 16bit mode mov ee_adrcntr,#ee_adrcntr16 ; Set for 16bit mov ee_maxadr,#ee_maxadr16 goto opening :eight ; ERROR!!!@Must be 16 bit mode call disp_2crlf mov w,#disp_error ; Display Error message call disp_string mov w,#disp_8bit call disp_string call disp_2crlf mov w,#disp_modeerr call disp_string call disp_crlf :loop ; It hangs in Mode Error goto :loop opening call disp_crlf mov w,#disp_open ; Greeting call disp_string mov w,#disp_version ; Display version number call disp_string call disp_crlf cje mode,#0,:eight ; Select mode mov w,#disp_16bit ; 16bit mode goto :finish :eight mov w,#disp_8bit ; 8bit :finish call disp_string call disp_crlf ;--------------------------------------- ; MAIN ;--------------------------------------- main call cmd_decode ; Get command goto main ;---------------------------------------- ; MESSAGE STRINGS ( 0 terminates string ) ;---------------------------------------- disp_str jmp pc+w str_base ; Base address ; Strings should not be ; Placed at address 0100h ; or greater str_open retw '93C57 EEPROM Programmer Ver.',0 str_version retw version_major,'.',version_minor,0 str_8bit retw ' [ 8bit mode ]',0 str_16bit retw ' [ 16bit mode ]',0 str_error retw 'Error',0 str_command retw 'COMMAND (D,W): ',0 str_dump retw '* MEMORY DUMP *',0 str_write retw '',0 str_address retw 'Start Address :00',0 str_adrerr retw 'Address Error',0 str_modeerr retw 'Set 16bit mode and Restart system',0 disp_open = str_open-str_base disp_version = str_version-str_base disp_8bit = str_8bit-str_base disp_16bit = str_16bit-str_base disp_error = str_error-str_base disp_cmd = str_command-str_base disp_dump = str_dump-str_base disp_write = str_write-str_base disp_address = str_address-str_base disp_adrerr = str_adrerr-str_base disp_modeerr = str_modeerr-str_base ;------------------------------------ ; COMMAND DECODE ;------------------------------------ cmd_decode call disp_crlf mov w,#disp_cmd ; Command prompt call disp_string call get_chr ; Get string from 232C mov w,rcv_byte call disp_byte call disp_2crlf cje rcv_byte,#'D',:dump ; D cje rcv_byte,#'d',:dump ; d cje rcv_byte,#'W',:write ; W cje rcv_byte,#'w',:write ; w mov w,#disp_error ; Not a command call disp_string call disp_2crlf goto cmd_decode ; Start it over again :dump call disp_crlf mov w,#disp_dump call disp_string call disp_crlf call mem_dump ; Memory dump call disp_2crlf goto :finish :write call disp_crlf mov w,#disp_write call disp_string call disp_crlf call set_address ; Set start address cjne quit_flag,#0,:finish ; Quit if ESC cjne skip_flag,#0,:finish ; Quit if CR call write_data ; Modify memory :finish ret ;------------------------------------ ; GET HEX DATA FROM RS232C ;------------------------------------ get_hex ; Returns value in hex_data clr hex_data clr skip_flag clr quit_flag get_hex2 clr ignore_flag call get_chr cjne rcv_byte,#code_cr,:skip2 ; Set skip_flag if CR inc skip_flag goto :finish :skip2 cjne rcv_byte,#code_esc,:skip3 ; ESC inc quit_flag goto :finish :skip3 call check_hex cjne ignore_flag,#0,get_hex2 clc rl hex_data ; Set high nibble rl hex_data rl hex_data rl hex_data :get_hex3 clr ignore_flag call get_chr cje rcv_byte,#code_cr,:get_hex3 ; Ignore CR cjne rcv_byte,#code_esc,:skip4 ; Quit if ESC inc quit_flag goto :finish :skip4 call check_hex cjne ignore_flag,#0,:get_hex3 cje first_byte,#0,:finish ; Do not wait CR if first byte :get_hex4 call get_chr ; Last input cjne rcv_byte,#code_esc,:get_hex5 ; ESC inc quit_flag goto :finish :get_hex5 cjne rcv_byte,#code_cr,:get_hex4 goto :finish ; Everything done :finish ret ; Data in hex_data ;----------------- check_hex cjb rcv_byte,#'0',:ignore ; Ignore illegal code cja rcv_byte,#'9',:skip3 mov w,rcv_byte ; Echo back call disp_byte mov w,rcv_byte and w,#0Fh ; Convert to binary goto :go_on :skip3 cjb rcv_byte,#'A',:ignore cjbe rcv_byte,#'F',:skip4 cjb rcv_byte,#'a',:ignore cja rcv_byte,#'f',:ignore :skip4 mov w,rcv_byte ; Echo back call disp_byte mov w,rcv_byte and w,#0Fh ; Convert to binary add w,#9 goto :go_on :ignore inc ignore_flag ; Set ignore flag :go_on or hex_data,w ; Store data into hex_data ret ;------------------------------------ ; GET A CHARACTER FROM RS232C ;------------------------------------ get_chr :start_bit snb serial_txd ; Find start bit jmp :start_bit call start_delay ; Wai half bit jb serial_txd,:start_bit ; Still there? mov bit_cntr,#8 ; Set bit counter clr rcv_byte ; Clear data buffer :receive call bit_delay ; Wait one bit time movb c,serial_txd ; Put data bit into carry rr rcv_byte ; Rotate djnz bit_cntr,:receive ; Received 8 bits? call bit_delay ; Wai for stop bit ret ;------------------------------------ ; DISPLAY DATA IN HEX VIA RS232C ;------------------------------------ disp_hex ; Display single byte in HEX mov temp,conv_byte rr temp rr temp rr temp rr temp call :disp_nbl mov temp,conv_byte ; Low nibble :disp_nbl and temp,#0Fh cjae temp,#0Ah,:alfa ; 0-9? or temp,#30h ; Yes, add 30h :output mov w,temp call disp_byte ret :alfa ; Convert to A-F sub temp,#09h or temp,#40h goto :output ;---------------------------------------- ; DISPLAY w CONTENTS VIA RS232C ;---------------------------------------- disp_byte ; Send one byte in W mov xmt_byte,w mov bit_cntr,#8 clrb serial_rxd ; Start bit call bit_delay :xmit rr xmt_byte ; Get next bit movb serial_rxd,c call bit_delay ; Bit rate djnz bit_cntr,:xmit setb serial_rxd ; Stop bit call bit_delay call bit_delay ret ;----------------------------- ; DISPLAY STRING ;----------------------------- disp_string mov msg_cntr,w :loop mov w,msg_cntr call disp_str and w,#0FFh jz :end call disp_byte inc msg_cntr goto :loop :end ret ;----------- disp_2crlf call disp_crlf ;----------- disp_crlf ; Send CR+LF to 232C mov w,#code_cr call disp_byte mov w,#code_lf call disp_byte ret ;----------- disp_space ;Send single space to 2322C mov w,#code_space call disp_byte ret ;----------------------------- ; MEMORY DUMP ;----------------------------- mem_dump clr ee_address ; Reset address :loop1 call disp_crlf mov conv_byte,#0 ; Display address call disp_hex mov conv_byte,ee_address call disp_hex :loop2 call disp_space call get_eedata ; Read 93C57 data mov conv_byte,ee_rdatah ; High byte (or data) call disp_hex ; Value returns in W cje mode,#0,:eight ; Skip if 8bit mode mov conv_byte,ee_rdatal ; Low byte call disp_hex :eight inc ee_address cje ee_address,ee_maxadr,:finish ; End of dump mov w,ee_address and w,#00000111b ; Check last 3 bits of address jnz :loop2 ; Next data goto :loop1 ; Next line :finish ret ;------------------------------ ; SET MEMORY START ADDRESS ;------------------------------ set_address mov w,#disp_address ; Start Addess prompt call disp_string clr quit_flag ; Clear flags clr skip_flag clr ignore_flag clr error_flag call get_hex ; Get start address cjne quit_flag,#0,:finish ; Quit if ESC cjne quit_flag,#0,:finish ; Quit if CR cjb hex_data,ee_maxadr,:sadr1 ; Check illegal address inc error_flag call disp_space mov w,#disp_adrerr ; Address error message call disp_string call disp_2crlf goto set_address :sadr1 mov ee_address,hex_data ; Set address :finish ret ;------------------------------ ; WRITE DATA INTO EEPROM ;------------------------------ write_data call disp_2crlf mov conv_byte,#0 ; Display address call disp_hex mov conv_byte,ee_address call disp_hex call disp_space call get_eedata ; Display current content mov conv_byte,ee_rdatah call disp_hex cje mode,#0,:eight ; Skip next byte if 8bit mode mov conv_byte,ee_rdatal call disp_hex :eight call disp_space clr first_byte ; First Byte call get_hex ; Fetch data from 232C cjne quit_flag,#0,:finish ; Quit if ESC cjne skip_flag,#0,:go_on ; Skip to next address if CR mov ee_wdatah,hex_data ; Store High byte of address cje mode,#0,:eight2 ; Skip if 8 bit mode inc first_byte ; Second byte call get_hex cjne quit_flag,#0,:finish ; Quit if ESC mov ee_wdatal,hex_data :eight2 cjne quit_flag,#0,:finish ; If ESC quit cjne skip_flag,#0,:go_on ; CR without data call enable_command ; Set EEPROM to write enable call enable_command2 ; Send Dummy data ; mov ee_address,#dummy_ewen ; Dummy address data for EWEN ; call send_address ; First 2bits are 11b clrb ee_cs call put_eedata ; Write into EEPROM call delay_2msec clrb ee_cs ; CS to L call delay_2msec call disable_command ; Write disable call disable_command2 ; Send Dummy data ; mov ee_address,#dummy_ewds ; Dummy address data for EWDS ; call send_address ; First 2bits are 00b clrb ee_cs cje error_flag,#0,:go_on ; No error call disp_crlf mov w,#disp_error ; Error occured call disp_string call disp_2crlf goto :finish :go_on inc ee_address ; Show next address cjne ee_address,ee_maxadr,write_data :finish ret ;----------------------------- ; PUT DATA INTO EEPROM 93C57 ;----------------------------- put_eedata ; Address in ee_address ; Data in ee_outdata clr error_flag call write_command ; Send write command to EEPROM call send_address ; Set address call send_data ; Send data ret ;----------------------------- ; GET DATA FROM EEPROM 93C57 ;----------------------------- get_eedata ; Address in ee_address ; Data into ee_rdata clr ee_rdatah clr ee_rdatal call read_command ; Send read command call send_address ; Set address call read_eedata ; Read data call ee_delay ; CS to L clrb ee_cs call ee_delay ret ;--------------------------------- ; SEND COMMAND, ADDRESS TO EEPROM ; * Multi entry, Single exit * ;--------------------------------- ; * READ COMMAND read_command clc clrb ee_cs ; CS to L call ee_delay setb ee_cs ; CS to H mov ee_cntr,#ee_cmdcntr ; 3bits for this command mov ee_buff,#ee_rdcmd goto ee_sendbit ; * WRITE ENABLE EEPROM enable_command ; Write Enable mode clc clrb ee_cs call ee_delay setb ee_cs mov ee_cntr,#ee_cmdcntr ; 3bits for this command ; First 2 bit of address should be 11b mov ee_buff,#ee_ewen ; EWEN command goto ee_sendbit enable_command2 ; Dummy data to complete EWEN mov ee_cntr,#ee_adrcntr16 mov ee_buff,#dummy_ewen goto ee_sendbit ; * WRITE DISABLE EEPEOM disable_command ; Write Disable mode clc clrb ee_cs call ee_delay setb ee_cs mov ee_cntr,#ee_cmdcntr ; 3bits for this command ; First 2 bit of address should be 00b mov ee_buff,#ee_ewds ; EWDS command goto ee_sendbit disable_command2 ; Dummy data to complete EWDS mov ee_cntr,#ee_adrcntr16 mov ee_buff,#dummy_ewds goto ee_sendbit ; * WRITE COMMAND write_command clc clrb ee_cs ; CS to L call ee_delay setb ee_cs ; CS to H mov ee_cntr,#ee_cmdcntr ; 3 bits for this command mov ee_buff,#ee_wrcmd goto ee_sendbit ; * SEND READ/WRITE ADDRESS send_address ; Assuming CS is kept H mov ee_cntr,ee_adrcntr ; Length of address (8 or 7) mov ee_buff,ee_address cje mode,#0,:eight rl ee_buff ; 16bit mode :eight goto ee_sendbit ; * SEND WRITE DATA send_data ; Assuming CS is kept H mov ee_cntr,#ee_datacntr ; 8bits for data mov ee_buff,ee_wdatah ; Data to write call ee_sendbit cje mode,#0,ee_sendfinish mov ee_buff,ee_wdatal goto ee_sendbit ;------------- ee_sendbit jnb ee_rdy,ee_sendbit ; Wait for READY status rl ee_buff ; Set data into Carry movb ee_di,c ; Output data call ee_delay setb ee_clk ; Clock to H call ee_delay clrb ee_clk ; Clock to L call ee_delay djnz ee_cntr,ee_sendbit call ee_delay ee_sendfinish ret ; Be care, CS is still H ;----------------------------- ; READ DATA FROM EEPROM ; Assuming address is set ;----------------------------- read_eedata ; Assuming CS is kept H mov ee_cntr,#ee_datacntr ; 8bits for data call :loop1 ; Read first byte mov ee_rdatah,ee_rdatal ; Read next data if 16bit mode cje mode,#0,:finish mov ee_cntr,#ee_datacntr ; 8bits for data :loop1 setb ee_clk ; Clock to H call ee_delay movb c,ee_do ; Get data rl ee_rdatal ; Set data clrb ee_clk ; Clock to L call ee_delay djnz ee_cntr,:loop1 :finish ret ;----------------------------- ; DELAY ROUTINES ;----------------------------- ee_delay ; EEPROM delay nop nop nop nop nop nop nop nop nop nop ret bit_delay mov delay_cntr,#rate_9600 ; Bit duration :loop djnz delay_cntr,:loop ret ;----------- start_delay mov delay_cntr,#rate_half ; Half bit duration :loop djnz delay_cntr,:loop ret ;----------- delay_2msec ; 2msec delay call delay_1msec delay_1msec ; 1msec delay mov delay_cntr,#0FFh ; Parameter for 3.58MHz :loop nop nop nop nop djnz delay_cntr,:loop ret end