; This software is distributed under GPLv2 and hence all the standard terms of ; NO WARRANTY apply to it. I created this software to educate myself and if ; you like you can use it in your own projects. But you must honor the terms ; of the GPLv2 in such a case and also give credit to the original. ; Enjoy and have fun ;-) ; EEPROM connecting lines _cs equ p2.0 so equ p2.1 _wp equ p2.2 _hold equ p2.3 sck equ p2.4 si equ p2.5 PAGE_SIZE equ 64D EOT equ 21h ; EEPROM Intructions READ equ 00000011b WRITE equ 00000010b WRDI equ 00000100b WREN equ 00000110b RDSR equ 00000101b WRSR equ 00000001b ;Batch mode commands BATCH_MODE equ 0FEh INTERACTIVE_MODE equ 0FDh BATCH_ADDRESS_WRITE equ 0F9h BATCH_WRITE_DATA equ 0FCh BATCH_READ_DATA equ 0FBh END_RW_CYCLE equ 0FAh BATCH_ADDRESS_READ equ 0F8h ; RAM addresses DATA_BYTE equ 60h ADDR_HIGH equ 61h ADDR_LOW equ 62h PERM_ADDR_HIGH equ 63h PERM_ADDR_LOW equ 64h SER_BYTE equ 65h PREV_BYTE equ 66h COUNT equ 67h RET_CODE equ 68h FLAG equ 69h TEMP equ 7ah BAT_MODE equ 7fh ;0 means interactive and 1 means batch mode. DUMP_ARRAY equ 70h ;Here we will store our bytes temporarily. org 0000h ljmp main ; bypassing the interrupt vectors org 0023h ;clr ea ;lcall serint_isr ;setb ea reti org 0030h ; Banner for SEAShell banner_l1: db ' /\' , 0ah, 0dh, 0 banner_l2: db ' {.-}', 0ah, 0dh, 0 banner_l3: db ' _____ ______ _____ _ _ _ ', 59 , '_.-' , 39, 92 ,0ah, 0dh, 0 banner_l4: db ' / ____| ____| /\ / ____| | | | | { _.}_' , 0ah, 0dh, 0 banner_l5: db '| (___ | |__ / \ | (___ | |__ ___| | | \.-',39, ' /', ' `', ',' , 0ah, 0dh, 0 banner_l6: db ' \___ \| __| / /\ \ \___ \| ', 39 ,'_ \ / _ \ | | \ | / ' , 0ah, 0dh, 0 banner_l7: db ' ____) | |____ / ____ \ ____) | | | | __/ | | -.\ | ,/ ' , 0ah, 0dh, 0 banner_l8: db '|_____/|______/_/ \_\_____/|_| |_|\___|_|_| ..- \|_/..-._' , 0ah, 0dh, 0 banner_l9: db 0ah, 0dh, ' (S)erial (E)Eprom (A)ccess (S)hell', 0ah, 0dh, 0 banner_l10: db 0ah, 0dh, ' (c) Seemanta Dutta, 2008', 0ah, 0dh, 0 DUMP_HELP_ITEM: db 0ah, 0dh, 'd - Dump EEPROM memory starting from current value of dump counter.', 0ah, 0dh, 0 WRITE_HELP_ITEM: db 'w - Write into particular memory location after providing memory address and the data.', 0ah, 0dh, 0 READ_HELP_ITEM: db 'r - Read from a particular memory location, after providing the memory address.', 0ah, 0dh, 0 RESET_COUNTER_HELP_ITEM: db 's - Reset the current value of dump counter to 0x0000.', 0ah, 0dh, 0 SET_COUNTER_HELP_ITEM: db 'c - Set dump counter value to desired value, to be entered interactively.',00ah, 0dh, 0 HELP_HELP_ITEM: db '? - Show this menu.', 0ah, 0dh, 0 BAT_MODE_CNF: db 'Mode set to batch mode...', 00ah, 0dh, 0 INT_MODE_CNF: db 'Mode set to interactive mode...', 0ah, 0dh, 0 DUMP_CTR_RESET: db 'Dump counter reset to 0x0000', 0ah, 0dh,0 ; *********** Start of hex digit validity table *********** ; presence of a 1 means valid and decimal digit, 2 means valid and hex digit validity_table: db 0 ;0 db 0 ;1 db 0 ;2 db 0 ;3 db 0 ;4 db 0 ;5 db 0 ;6 db 0 ;7 db 0 ;8 db 0 ;9 db 0 ;10 db 0 ;11 db 0 ;12 db 0 ;13 db 0 ;14 db 0 ;15 db 0 ;16 db 0 ;17 db 0 ;18 db 0 ;19 db 0 ;20 db 0 ;21 db 0 ;22 db 0 ;23 db 0 ;24 db 0 ;25 db 0 ;26 db 0 ;27 db 0 ;28 db 0 ;29 db 0 ;30 db 0 ;31 db 0 ;32 db 0 ;33 db 0 ;34 db 0 ;35 db 0 ;36 db 0 ;37 db 0 ;38 db 0 ;39 db 0 ;40 db 0 ;41 db 0 ;42 db 0 ;43 db 0 ;44 db 0 ;45 db 0 ;46 db 0 ;47 db 1 ;48 - 0 db 1 ;49 - 1 db 1 ;50 - 2 db 1 ;51 - 3 db 1 ;52 - 4 db 1 ;53 - 5 db 1 ;54 - 6 db 1 ;55 - 7 db 1 ;56 - 8 db 1 ;57 - 9 db 0 ;58 db 0 ;59 db 0 ;60 db 0 ;61 db 0 ;62 db 0 ;63 db 0 ;64 db 2 ;65 - A db 2 ;66 - B db 2 ;67 - C db 2 ;68 - D db 2 ;69 - E db 2 ;70 - F db 0 ;71 db 0 ;72 db 0 ;73 db 0 ;74 db 0 ;75 db 0 ;76 db 0 ;77 db 0 ;78 db 0 ;79 db 0 ;80 db 0 ;81 db 0 ;82 db 0 ;83 db 0 ;84 db 0 ;85 db 0 ;86 db 0 ;87 db 0 ;88 db 0 ;89 db 0 ;90 db 0 ;91 db 0 ;92 db 0 ;93 db 0 ;94 db 0 ;95 db 0 ;96 db 2 ;97 - a db 2 ;98 - b db 2 ;99 - c db 2 ;100 - d db 2 ;101 - e db 2 ;102 - f db 0 ;103 db 0 ;104 db 0 ;105 db 0 ;106 db 0 ;107 db 0 ;108 db 0 ;109 db 0 ;110 db 0 ;111 db 0 ;112 db 0 ;113 db 0 ;114 db 0 ;115 db 0 ;116 db 0 ;117 db 0 ;118 db 0 ;119 db 0 ;120 db 0 ;121 db 0 ;122 db 0 ;123 db 0 ;124 db 0 ;125 db 0 ;126 db 0 ;127 db 0 ;128 db 0 ;129 db 0 ;130 db 0 ;131 db 0 ;132 db 0 ;133 db 0 ;134 db 0 ;135 db 0 ;136 db 0 ;137 db 0 ;138 db 0 ;139 db 0 ;140 db 0 ;141 db 0 ;142 db 0 ;143 db 0 ;144 db 0 ;145 db 0 ;146 db 0 ;147 db 0 ;148 db 0 ;149 db 0 ;150 db 0 ;151 db 0 ;152 db 0 ;153 db 0 ;154 db 0 ;155 db 0 ;156 db 0 ;157 db 0 ;158 db 0 ;159 db 0 ;160 db 0 ;161 db 0 ;162 db 0 ;163 db 0 ;164 db 0 ;165 db 0 ;166 db 0 ;167 db 0 ;168 db 0 ;169 db 0 ;170 db 0 ;171 db 0 ;172 db 0 ;173 db 0 ;174 db 0 ;175 db 0 ;176 db 0 ;177 db 0 ;178 db 0 ;179 db 0 ;180 db 0 ;181 db 0 ;182 db 0 ;183 db 0 ;184 db 0 ;185 db 0 ;186 db 0 ;187 db 0 ;188 db 0 ;189 db 0 ;190 db 0 ;191 db 0 ;192 db 0 ;193 db 0 ;194 db 0 ;195 db 0 ;196 db 0 ;197 db 0 ;198 db 0 ;199 db 0 ;200 db 0 ;201 db 0 ;202 db 0 ;203 db 0 ;204 db 0 ;205 db 0 ;206 db 0 ;207 db 0 ;208 db 0 ;209 db 0 ;210 db 0 ;211 db 0 ;212 db 0 ;213 db 0 ;214 db 0 ;215 db 0 ;216 db 0 ;217 db 0 ;218 db 0 ;219 db 0 ;220 db 0 ;221 db 0 ;222 db 0 ;223 db 0 ;224 db 0 ;225 db 0 ;226 db 0 ;227 db 0 ;228 db 0 ;229 db 0 ;230 db 0 ;231 db 0 ;232 db 0 ;233 db 0 ;234 db 0 ;235 db 0 ;236 db 0 ;237 db 0 ;238 db 0 ;239 db 0 ;240 db 0 ;241 db 0 ;242 db 0 ;243 db 0 ;244 db 0 ;245 db 0 ;246 db 0 ;247 db 0 ;248 db 0 ;249 db 0 ;250 db 0 ;251 db 0 ;252 db 0 ;253 db 0 ;254 db 0 ;255 ; *********** End of hex digit validity table *********** prompt: db 0ah, 0dh, 'SEAShell> ',0 enter_address: db 'Enter Address to read/write : ', 0 address_error: db 0ah, 0dh, 'Invalid hex value entered.', 0ah, 0dh, 'Please Enter value from the beginning again: ', 0 enter_data: db 0ah, 0dh, 'Enter Data to be written: ', 0 data_at: db 0ah, 0dh, 'Data at above address is: ', 0 enter_new_counter: db 'Enter new value of dump counter: ', 0 invalid_command: db 'Invalid command!', 0 main: clr BAT_MODE ;We start out in Interactive mode. ALWAYS. lcall init_ser_port lcall init_eeprom mov PERM_ADDR_LOW,#00h mov PERM_ADDR_HIGH,#00h lcall send_newline mov dptr,#banner_l1 lcall send_string mov dptr,#banner_l2 lcall send_string mov dptr,#banner_l3 lcall send_string mov dptr,#banner_l4 lcall send_string mov dptr,#banner_l5 lcall send_string mov dptr,#banner_l6 lcall send_string mov dptr,#banner_l7 lcall send_string mov dptr,#banner_l8 lcall send_string mov dptr,#banner_l9 lcall send_string mov dptr,#banner_l10 lcall send_string _show_prompt: mov dptr,#prompt lcall send_string lcall recv_cmd lcall parse_cmd sjmp _show_prompt send_string: push acc _again: clr a movc a,@a+dptr jz _done mov sbuf,a jnb ti,$ clr ti inc dptr sjmp _again _done: jnb BAT_MODE,_fwd8 ;send the EOT after each line when in batch mode. mov SER_BYTE,#EOT lcall send_one_char _fwd8: pop acc ret serint_isr: ;isr for ri & ti jb ti,_trans mov SER_BYTE,sbuf ;received interrupt clr ti lcall parse_cmd ret _trans: clr ti ;transmit interrupt ret ;This routine jumps to the appropriate jump table from where control reaches the appropriate ;handler for the command given by the user. parse_cmd: mov a,#'d' xrl a,SER_BYTE jz __dump mov a,#'w' xrl a,SER_BYTE jz __write mov a,#'r' xrl a,SER_BYTE jz __read_at mov a,#'s' xrl a,SER_BYTE jz __reset mov a,#'c' xrl a,SER_BYTE jz __set_dump_counter mov a,#0ah xrl a,SER_BYTE jz __next_cmd mov a,#BATCH_MODE xrl a,SER_BYTE jz __batch_mode mov a,#INTERACTIVE_MODE xrl a,SER_BYTE jz __interactive_mode mov a,#BATCH_WRITE_DATA xrl a,SER_BYTE jz __batch_write_data mov a,#BATCH_READ_DATA xrl a,SER_BYTE jz __batch_read_data mov a,#END_RW_CYCLE xrl a,SER_BYTE jz __end_rw_cycle mov a,#BATCH_ADDRESS_WRITE xrl a,SER_BYTE jz __batch_address_write mov a,#BATCH_ADDRESS_READ xrl a,SER_BYTE jz __batch_address_read mov a,#'?' xrl a,SER_BYTE jz __show_menu mov dptr,#invalid_command lcall send_string ret ; We are using a jump table because jz instructions can't reach the routines after 128 bytes and ; the assembler cribs and quits saying unreachable label. __dump: ljmp _dump __write: ljmp _write __read_at: ljmp _read_at __reset: ljmp _reset __set_dump_counter: ljmp _set_dump_counter __next_cmd: ljmp _next_cmd __batch_mode: ljmp _batch_mode __interactive_mode: ljmp _interactive_mode __batch_write_data: ljmp _batch_write_data __batch_read_data: ljmp _batch_read_data __end_rw_cycle: ljmp _end_rw_cycle __batch_address_write: ljmp _batch_address_write __batch_address_read: ljmp _batch_address_read __show_menu: ljmp _show_menu _dump: lcall dump_eeprom_data ret _write: mov FLAG,#00h lcall write_into_eeprom ret _read_at: mov FLAG,#02h ;02H means the the routine will read, not write lcall write_into_eeprom ret _reset: mov PERM_ADDR_LOW,#00h ;resetting the address dump counter mov PERM_ADDR_HIGH,#00h mov dptr,#DUMP_CTR_RESET lcall send_string ret _set_dump_counter: lcall set_counter ret _next_cmd: ret _batch_mode: setb BAT_MODE mov DPTR,#BAT_MODE_CNF lcall send_string ret _interactive_mode: clr BAT_MODE MOV DPTR,#INT_MODE_CNF lcall send_string ret _batch_write_data: mov dptr,#enter_data lcall send_string _write_next_byte: lcall recv_one_char mov DATA_BYTE,SER_BYTE lcall shift_out djnz TEMP,_write_next_byte ;lcall chip_deselect ;this ends the write cycle ret _batch_read_data: lcall shift_in mov SER_BYTE,DATA_BYTE lcall send_one_char ;djnz TEMP,_batch_read_data ret _end_rw_cycle: lcall chip_deselect ret _batch_address_write: mov DPTR,#enter_address lcall send_string lcall recv_one_char mov ADDR_LOW,SER_BYTE lcall recv_one_char mov ADDR_HIGH,SER_BYTE lcall recv_one_char mov TEMP,SER_BYTE ;count of characters to write in all, maximum value is 64 ;mov DPTR,#enter_data ;lcall send_string lcall init_eeprom_write ret _batch_address_read: mov DPTR,#enter_address lcall send_string lcall recv_one_char mov ADDR_LOW,SER_BYTE lcall recv_one_char mov ADDR_HIGH,SER_BYTE lcall recv_one_char mov TEMP,SER_BYTE ;count of characters to read in all, maximum value is 255 lcall init_eeprom_read ret _show_menu: mov dptr,#DUMP_HELP_ITEM lcall send_string mov dptr,#WRITE_HELP_ITEM lcall send_string mov dptr,#READ_HELP_ITEM lcall send_string mov dptr,#RESET_COUNTER_HELP_ITEM lcall send_string mov dptr,#SET_COUNTER_HELP_ITEM lcall send_string mov dptr,#HELP_HELP_ITEM lcall send_string ret set_counter: ;This routine will piggy back on top of the ADDR_HIGH and ADDR_LOW variables. mov dptr,#enter_new_counter lcall send_string lcall get_hibyte_msn mov a,RET_CODE jnz set_counter lcall get_hibyte_lsn mov a,RET_CODE jnz set_counter lcall get_lowbyte_msn mov a,RET_CODE jnz set_counter lcall get_lowbyte_lsn mov a,RET_CODE jnz set_counter mov PERM_ADDR_HIGH,ADDR_HIGH ;set the 'permanent' variables mov PERM_ADDR_LOW,ADDR_LOW ret recv_cmd: mov PREV_BYTE,#0ah _b2: lcall recv_one_char mov a,#0dh xrl a,SER_BYTE jz _fwd mov PREV_BYTE,SER_BYTE jmp _b2 _fwd: mov SER_BYTE,PREV_BYTE ret write_into_eeprom: mov dptr,#enter_address lcall send_string ;Get all the address bytes. M(L)SN == Most(Least) Significant Nibble lcall get_hibyte_msn mov a,RET_CODE jnz write_into_eeprom lcall get_hibyte_lsn mov a,RET_CODE jnz write_into_eeprom lcall get_lowbyte_msn mov a,RET_CODE jnz write_into_eeprom lcall get_lowbyte_lsn mov a,RET_CODE jnz write_into_eeprom mov a,FLAG jnz _read_only ;NOT zero, 02h means it is read only operation, not write operation. ;Step1: call the init routine lcall init_eeprom_write ;Step2: get the data to write mov dptr,#enter_data lcall send_string lcall get_data_byte ;Step3: Write the data and end the write cycle lcall eeprom_write_byte jmp _fwd6 _read_only: lcall init_eeprom_read ;this will initialize the start address to read from. Address is ;already in ADDR_LOW and ADDR_HIGH lcall eeprom_read_byte mov dptr,#data_at lcall send_string mov SER_BYTE, DATA_BYTE lcall print_one_num_hex _fwd6: lcall chip_deselect ;this ends the read/write cycle. ret get_data_byte: ;Although this routine says it gets DATA_BYTE, but it returns the data ;by using the variable which usually stores the address high byte. ;A sacrifice of convention to avoid writing another routine. lcall get_hibyte_msn mov a,RET_CODE jnz get_data_byte lcall get_hibyte_lsn mov a,RET_CODE jnz get_data_byte mov DATA_BYTE,ADDR_HIGH ret get_hibyte_msn: lcall recv_one_char mov DATA_BYTE,SER_BYTE lcall check_validity mov a,RET_CODE jnz _disp_error1 ;jump to error branch ;Non error code : need to convert the value into hex digit here. mov a,SER_BYTE mov dptr,#validity_table movc a,@a+dptr rrc a ;checking if lsb is a 1 or 0. 1 means Acc had 1 and 0 means Acc had 2. jc _decimal_1 mov a,SER_BYTE anl a,#00001111b add a,#9d jmp _fwd_1 _decimal_1: mov a,SER_BYTE anl a,#00001111b _fwd_1: rl a rl a rl a rl a ;shifting the digit left by 4 to create msb mov ADDR_HIGH,a ;mov SER_BYTE,ADDR_HIGH ;lcall print_one_num_hex ret _disp_error1: ;error branch code mov dptr,#address_error lcall send_string lcall send_newline ;return with error code here ret get_hibyte_lsn: lcall recv_one_char mov DATA_BYTE,SER_BYTE lcall check_validity mov a,RET_CODE jnz _disp_error2 ;jump to error branch ;Non error code : need to convert the value into hex digit here. mov a,SER_BYTE mov dptr,#validity_table movc a,@a+dptr rrc a ;checking if lsb is a 1 or 0. 1 means Acc had 1 and 0 means Acc had 2. jc _decimal_2 mov a,SER_BYTE anl a,#00001111b add a,#9d jmp _fwd_2 _decimal_2: mov a,SER_BYTE anl a,#00001111b ;no need to shift anything here as it is lsn _fwd_2: orl ADDR_HIGH,a ;ADDR_HIGH ;ADDR_HIGH now contains both MSN and LSN of the HIGH ADDRESS byte ;mov SER_BYTE,ADDR_HIGH ;lcall print_one_num_hex ret _disp_error2: ;error branch code mov dptr,#address_error lcall send_string lcall send_newline ;return with error code here ret get_lowbyte_msn: lcall recv_one_char mov DATA_BYTE,SER_BYTE lcall check_validity mov a,RET_CODE jnz _disp_error3 ;jump to error branch ;Non error code : need to convert the value into hex digit here. mov a,SER_BYTE mov dptr,#validity_table movc a,@a+dptr rrc a ;checking if lsb is a 1 or 0. 1 means Acc had 1 and 0 means Acc had 2. jc _decimal_3 mov a,SER_BYTE anl a,#00001111b add a,#9d jmp _fwd_3 _decimal_3: mov a,SER_BYTE anl a,#00001111b _fwd_3: rl a rl a rl a rl a ;shifting the digit left by 4 to create msb mov ADDR_LOW,a ;mov SER_BYTE,ADDR_LOW ;lcall print_one_num_hex ret _disp_error3: ;error branch code mov dptr,#address_error lcall send_string lcall send_newline ;return with error code here ret get_lowbyte_lsn: lcall recv_one_char mov DATA_BYTE,SER_BYTE lcall check_validity mov a,RET_CODE jnz _disp_error4 ;jump to error branch ;Non error code : need to convert the value into hex digit here. mov a,SER_BYTE mov dptr,#validity_table movc a,@a+dptr rrc a ;checking if lsb is a 1 or 0. 1 means Acc had 1 and 0 means Acc had 2. jc _decimal_4 mov a,SER_BYTE anl a,#00001111b add a,#9d jmp _fwd_4 _decimal_4: mov a,SER_BYTE anl a,#00001111b ;no need to shift anything here as it is lsn _fwd_4: orl ADDR_LOW,a ;ADDR_LOW ;ADDR_LOW now contains both MSN and LSN of the HIGH ADDRESS byte ;mov SER_BYTE,ADDR_LOW ;lcall print_one_num_hex ret _disp_error4: ;error branch code mov dptr,#address_error lcall send_string lcall send_newline ;return with error code here ret check_validity: push acc mov RET_CODE,#00h ;initializing with SUCCESS return code mov dptr,#validity_table mov a,DATA_BYTE movc a,@a+dptr jnz _success ;1 or 2 means valid, 0 means invalid ;failure case here mov RET_CODE,#01h _success: pop acc ret dump_eeprom_data: lcall send_newline mov COUNT,#PAGE_SIZE mov ADDR_HIGH,PERM_ADDR_HIGH mov ADDR_LOW,PERM_ADDR_LOW lcall init_eeprom_read mov r0,#DUMP_ARRAY ;initialize the r1 index to start of dump array. mov TEMP,#00h _back2: mov a,TEMP mov b,#08h div ab mov a,b jnz _fwd2 ;means address is NOT a multiple of 8 mov a,TEMP jz _cont mov r0,#DUMP_ARRAY ;re-initialize r1 for next line of data ;call the routine here to dump out the bytes accumulated so far in the DUMP_ARRAY lcall dump_dump_array _cont: lcall send_newline mov SER_BYTE,PERM_ADDR_HIGH lcall print_one_num_hex mov SER_BYTE,PERM_ADDR_LOW lcall print_one_num_hex mov SER_BYTE,#':' lcall send_one_char lcall send_space lcall send_space _fwd2: lcall eeprom_read_byte mov SER_BYTE,DATA_BYTE lcall print_one_num_hex mov SER_BYTE,#'(' lcall send_one_char ;check if value in data byte is below 32 Decimal clr C mov a,#31D subb a, DATA_BYTE ; a - DATA_BYTE | CY=1->-ve | CY=0->+ve jc _printable mov SER_BYTE,#'.' jmp _fwd4 _printable: mov SER_BYTE,DATA_BYTE _fwd4: lcall send_one_char ;store whatever we wanted to print in our array also mov @r0,SER_BYTE ;increment the index variable inc r0 mov SER_BYTE,#')' lcall send_one_char lcall send_space inc TEMP inc PERM_ADDR_LOW mov a,PERM_ADDR_LOW jz _inc_hibyte jmp _fwd7 ;no overflow occurs so skip everything _inc_hibyte: inc PERM_ADDR_HIGH mov a,PERM_ADDR_HIGH jb acc.7,_reset_addr ;msb in acc high means overflow has happened from 7f to 80. jmp _fwd7 ;no overflow occurs so skip everything _reset_addr: mov PERM_ADDR_HIGH,#00h mov PERM_ADDR_LOW,#00h _fwd7: djnz COUNT,_back2 lcall dump_dump_array ;This is the last dump array dump lcall chip_deselect ;to end the read cycle ret dump_dump_array: ;We put 2 spaces between the dump and the hex values. mov SER_BYTE,#' ' lcall send_one_char mov SER_BYTE,#' ' lcall send_one_char ;Now set the counter to dump eight bytes. mov r2,#8h mov r1,#DUMP_ARRAY _repeat: mov SER_BYTE,@r1 lcall send_one_char inc r1 djnz r2,_repeat ret print_one_num: push acc push b mov a,SER_BYTE mov b,#10D div ab add a,#30h mov sbuf,a jnb ti,$ clr ti mov a,b add a,#30h mov sbuf,a jnb ti,$ clr ti pop b pop acc ret print_one_num_hex: push acc push b mov a,SER_BYTE mov b,#10h div ab lcall xform_a ;add a,#30h mov sbuf,a jnb ti,$ clr ti mov a,b ;add a,#30h lcall xform_a mov sbuf,a jnb ti,$ clr ti pop b pop acc ret ;A --> 0-F xform_a: push b ;saving it for the time being push acc ;11d clr c mov b,a ;b=11d mov a,#9d ;a=10d subb a,b ;a=a(10)-b(11); a=0 jnc _fwd3 ;result is +ve, so hex digit lies in the range A-F pop acc ;11d clr c subb a,#10d ;1 add a,#'A' pop b ret _fwd3: pop acc ;result is -ve, so hex digit lies in the range 0-9 add a,#30h pop b ret send_space: mov SER_BYTE,#' ' lcall send_one_char ret send_newline: mov SER_BYTE,#0ah lcall send_one_char mov SER_BYTE,#0dh lcall send_one_char ret ; Establish default values for EEPROM bus lines init_eeprom: setb _cs ;_cs default as HIGH : to NOT select chip when not needed setb _wp ;_wp default as HIGH : to allow writes setb _hold ;_hold default as HIGH : to access device always , unless overridden setb sck ;sck default as HIGH : as idle condition setb so ;so default as HIGH : as idle condition setb si ;si default as HIGH : as idle condition ret chip_select: setb _cs nop clr _cs ret chip_deselect: clr _cs nop setb _cs ret ; WRITE Specific init routine init_eeprom_write: ;must be immediately followed by eeprom_write_byte clr _cs ;setting _cs to low first mov DATA_BYTE,#WREN lcall shift_out setb _cs ;bringing up _cs to HIGH again to set write latch nop ; some delay before asserting _cs again clr _cs ;this would enable the write latch mov DATA_BYTE,#WRITE lcall shift_out mov DATA_BYTE,ADDR_HIGH lcall shift_out mov DATA_BYTE,ADDR_LOW lcall shift_out ret eeprom_write_byte: ;clr _cs lcall shift_out ;setb _cs ;de-asserting _cs after writing is over ret init_eeprom_read: ;must be immediately followed by eeprom_read_byte clr _cs ;asserting _cs just before reading mov DATA_BYTE,#READ lcall shift_out ;Sending address to read from mov DATA_BYTE,ADDR_HIGH lcall shift_out mov DATA_BYTE,ADDR_LOW lcall shift_out ret eeprom_read_byte: ;read the data byte now lcall shift_in ret shift_out: push acc push psw ;data to shift out is in A, and we have to shift it out, MSB first via si mov a,DATA_BYTE mov r3,#8 clr C _back: rlc A mov si,C clr sck ;lowering clock from idle level(HIGH) nop ;some delay setb sck ;raising clock to latch bit nop ;again some delay to allow EEPROM to digest what we just sent djnz r3,_back ;repeat for all bits in A pop psw pop acc ret shift_in: push acc push psw ;data would be shifted in via so line mov r3,#8 clr C mov a,#00h setb so _back1: clr sck nop setb sck ;this will cause EEPROM to vomit out the bit onto so nop nop mov C,so rlc A ;this rotation would pack the bits starting with MSB and then proceed to LSB nop ;some delay djnz r3,_back1 mov DATA_BYTE,a pop psw pop acc ret init_ser_port: ;Initializing the serial baud rate generator ;mov ie,#10010100b ;enabling the serial port interrupt and int1 ;setb it1 ;to set interrupt 1 as edge triggered ;clr ea mov tmod, #20h ;timer 1, mode 2(auto reload mode) mov th1,#-3 ;9600 baud rate mov scon,#50h ;8-bit, 1 stop bit, ren enabled setb tr1 ;start timer 1 ret send_one_char: mov sbuf,SER_BYTE jnb ti,$ clr ti ret recv_one_char: jnb ri,$ mov SER_BYTE,sbuf clr ri ret delay_5ms: mov r1, #250 ; write cycle time dly5ms1: lcall dly20us ; ~250 * 20us = 5msec djnz r1, dly5ms1 ret dly20us: mov r2, #38 ; 0.5 usec dly20: djnz r2, dly20 ; 0.5 usec * 38 = 19 usecs ret ; 0.5 usec end