;**** **** **** **** **** ; ; BLHeli program for controlling brushless motors in helicopters and multirotors ; ; Copyright 2011, 2012 Steffen Skaug ; This program is distributed under the terms of the GNU General Public License ; ; This file is part of BLHeli. ; ; BLHeli is free software: you can redistribute it and/or modify ; it under the terms of the GNU General Public License as published by ; the Free Software Foundation, either version 3 of the License, or ; (at your option) any later version. ; ; BLHeli is distributed in the hope that it will be useful, ; but WITHOUT ANY WARRANTY; without even the implied warranty of ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ; GNU General Public License for more details. ; ; You should have received a copy of the GNU General Public License ; along with BLHeli. If not, see . ; ;**** **** **** **** **** ; ; BLHeliTxPgm SiLabs ; ; EEPROM is not available in SiLabs MCUs ; Therefore a segment of the flash is used as "EEPROM" ; ;**** **** **** **** **** ;**** **** **** **** **** **** **** **** **** **** **** **** **** ; ; Read all eeprom parameters routine ; ; No assumptions ; ;**** **** **** **** **** **** **** **** **** **** **** **** **** read_all_eeprom_parameters: ; Check initialized signature mov DPTR, #Eep_Initialized_L mov Temp1, #Bit_Access call read_eeprom_byte mov A, Bit_Access IF MODE == 0 cjne A, #0A5h, read_eeprom_store_defaults ENDIF IF MODE == 1 cjne A, #05Ah, read_eeprom_store_defaults ENDIF IF MODE == 2 cjne A, #055h, read_eeprom_store_defaults ENDIF inc DPTR ; Now Eep_Initialized_H call read_eeprom_byte mov A, Bit_Access IF MODE == 0 cjne A, #05Ah, read_eeprom_store_defaults ENDIF IF MODE == 1 cjne A, #0A5h, read_eeprom_store_defaults ENDIF IF MODE == 2 cjne A, #0AAh, read_eeprom_store_defaults ENDIF jmp read_eeprom_read read_eeprom_store_defaults: call set_default_parameters call erase_and_store_all_in_eeprom jmp read_eeprom_exit read_eeprom_read: ; Read eeprom IF MODE == 0 ;Main mov DPTR, #Eep_Pgm_Gov_P_Gain ENDIF IF MODE == 1 ; Tail mov DPTR, #_Eep_Pgm_Gov_P_Gain ENDIF mov Temp1, #Pgm_Gov_P_Gain mov Temp4, #10 IF MODE == 2 ; multi mov DPTR, #Eep_Pgm_Fir_Key mov Temp1, #Pgm_Fir_Key mov Temp4, #12 ENDIF read_eeprom_block1: call read_eeprom_byte inc DPTR inc Temp1 djnz Temp4, read_eeprom_block1 mov DPTR, #Eep_Enable_TX_Program mov Temp1, #Pgm_Enable_TX_Program mov Temp4, #21 ; 21 parameters read_eeprom_block2: call read_eeprom_byte inc DPTR inc Temp1 djnz Temp4, read_eeprom_block2 mov DPTR, #Eep_Dummy ; Set pointer to uncritical area read_eeprom_exit: ret ;**** **** **** **** **** **** **** **** **** **** **** **** **** ; ; Erase flash and store all parameter value in EEPROM routine ; ; No assumptions ; ;**** **** **** **** **** **** **** **** **** **** **** **** **** erase_and_store_all_in_eeprom: clr EA ; Disable interrupts ; call read_tags ;2015-02-11 call erase_flash ; Erase flash mov DPTR, #Eep_FW_Main_Revision ; Store firmware main revision mov A, #EEPROM_FW_MAIN_REVISION call write_eeprom_byte_from_acc inc DPTR ; Now firmware sub revision mov A, #EEPROM_FW_SUB_REVISION call write_eeprom_byte_from_acc inc DPTR ; Now layout revision mov A, #EEPROM_LAYOUT_REVISION call write_eeprom_byte_from_acc ; Write eeprom IF MODE == 0 ;Main mov DPTR, #Eep_Pgm_Gov_P_Gain ENDIF IF MODE == 1 ; Tail mov DPTR, #_Eep_Pgm_Gov_P_Gain ENDIF mov Temp1, #Pgm_Gov_P_Gain mov Temp4, #10 IF MODE == 2 ;multi mov DPTR, #Eep_Pgm_Fir_Key mov Temp1, #Pgm_Fir_Key mov Temp4, #12 ENDIF write_eeprom_block1: call write_eeprom_byte inc DPTR inc Temp1 djnz Temp4, write_eeprom_block1 mov DPTR, #Eep_Enable_TX_Program mov Temp1, #Pgm_Enable_TX_Program mov Temp4, #21 ; 21 parameters write_eeprom_block2: call write_eeprom_byte inc DPTR inc Temp1 djnz Temp4, write_eeprom_block2 ; call write_tags ;2015-02-11 call write_eeprom_signature mov DPTR, #Eep_Dummy ; Set pointer to uncritical area ret ;**** **** **** **** **** **** **** **** **** **** **** **** **** CSEG AT 1C00h ; Last code segment. Take care that there is enough space! ;**** **** **** **** **** **** **** **** **** **** **** **** **** ;**** **** **** **** **** **** **** **** **** **** **** **** **** ; ; Read eeprom byte routine ; ; Gives data in A and in address given by Temp1. Assumes address in DPTR ; Also assumes address high byte to be zero ; ;**** **** **** **** **** **** **** **** **** **** **** **** **** read_eeprom_byte: clr A movc A, @A+DPTR ; Read from flash mov @Temp1, A ret ;**** **** **** **** **** **** **** **** **** **** **** **** **** ; ; Write eeprom byte routine ; ; Assumes data in address given by Temp1, or in accumulator. Assumes address in DPTR ; Also assumes address high byte to be zero ; ;**** **** **** **** **** **** **** **** **** **** **** **** **** write_eeprom_byte: mov A, @Temp1 write_eeprom_byte_from_acc: orl PSCTL, #01h ; Set the PSWE bit anl PSCTL, #0FDh ; Clear the PSEE bit mov RSTSRC, #02h ; Set VDD monitor as a reset source (PORSF) mov FLKEY, #0A5h ; First key code mov FLKEY, #0F1h ; Second key code movx @DPTR, A ; Write to flash anl PSCTL, #0FEh ; Clear the PSWE bit ret ;**** **** **** **** **** **** **** **** **** **** **** **** **** ; ; Erase flash routine (erases the flash segment used for "eeprom" variables) ; ; No assumptions ; ;**** **** **** **** **** **** **** **** **** **** **** **** **** erase_flash: orl PSCTL, #02h ; Set the PSEE bit orl PSCTL, #01h ; Set the PSWE bit mov RSTSRC, #02h ; Set VDD monitor as a reset source (PORSF) mov FLKEY, #0A5h ; First key code mov FLKEY, #0F1h ; Second key code mov DPTR, #Eep_Initialized_L movx @DPTR, A anl PSCTL, #0FCh ; Clear the PSEE and PSWE bits ret ;**** **** **** **** **** **** **** **** **** **** **** **** **** ; ; Write eeprom signature routine ; ; No assumptions ; ;**** **** **** **** **** **** **** **** **** **** **** **** **** write_eeprom_signature: IF MODE == 0 mov DPTR, #Eep_Initialized_L mov A, #0A5h call write_eeprom_byte_from_acc mov DPTR, #Eep_Initialized_H mov A, #05Ah call write_eeprom_byte_from_acc ENDIF IF MODE == 1 mov DPTR, #Eep_Initialized_L mov A, #05Ah call write_eeprom_byte_from_acc mov DPTR, #Eep_Initialized_H mov A, #0A5h call write_eeprom_byte_from_acc ENDIF IF MODE == 2 mov DPTR, #Eep_Initialized_L mov A, #055h call write_eeprom_byte_from_acc mov DPTR, #Eep_Initialized_H mov A, #0AAh call write_eeprom_byte_from_acc ENDIF ret ;**** **** **** **** **** **** **** **** **** **** **** **** **** ; ; Read all tags from flash and store in temporary storage ; ; No assumptions ; ;**** **** **** **** **** **** **** **** **** **** **** **** **** read_tags: mov Temp3, #48 ; Number of tags mov Temp2, #Tag_Temporary_Storage ; Set RAM address mov Temp1, #Bit_Access mov DPTR, #Eep_ESC_Layout ; Set flash address read_tag: call read_eeprom_byte mov A, Bit_Access mov @Temp2, A ; Write to RAM inc Temp2 inc DPTR djnz Temp3, read_tag ret ;**** **** **** **** **** **** **** **** **** **** **** **** **** ; ; Write all tags from temporary storage and store in flash ; ; No assumptions ; ;**** **** **** **** **** **** **** **** **** **** **** **** **** write_tags: mov Temp3, #48 ; Number of tags mov Temp2, #Tag_Temporary_Storage ; Set RAM address mov DPTR, #Eep_ESC_Layout ; Set flash address write_tag: mov A, @Temp2 ; Read from RAM call write_eeprom_byte_from_acc inc Temp2 inc DPTR djnz Temp3, write_tag ret ;**** **** **** **** **** **** **** **** **** **** **** **** **** ; ; Store new parameter value in ram routine ; ; No assumptions ; ;**** **** **** **** **** **** **** **** **** **** **** **** **** store_new_value_in_ram: mov Temp4, Tx_Pgm_Func_No ; Function no mov Temp1, Tx_Pgm_Paraval_No ; Parameter value no IF MODE == 0 store_main_func_1: cjne Temp4, #1, store_main_func_2 mov Temp2, #Pgm_Gov_P_Gain store_main_func_2: cjne Temp4, #2, store_main_func_3 mov Temp2, #Pgm_Gov_I_Gain store_main_func_3: cjne Temp4, #3, store_main_func_4 mov Temp2, #Pgm_Gov_Mode store_main_func_4: cjne Temp4, #4, store_main_func_5 mov Temp2, #Pgm_Gov_Range store_main_func_5: cjne Temp4, #5, store_main_func_6 mov Temp2, #Pgm_Low_Voltage_Lim store_main_func_6: cjne Temp4, #6, store_main_func_7 mov Temp2, #Pgm_Startup_Pwr store_main_func_7: cjne Temp4, #7, store_main_func_8 mov Temp2, #Pgm_Comm_Timing store_main_func_8: cjne Temp4, #8, store_main_func_9 mov Temp2, #Pgm_Pwm_Freq store_main_func_9: cjne Temp4, #9, store_main_func_10 mov Temp2, #Pgm_Demag_Comp store_main_func_10: cjne Temp4, #10, store_main_func_11 mov Temp2, #Pgm_Direction store_main_func_11: cjne Temp4, #11, store_in_ram_exit mov Temp2, #Pgm_Input_Pol ENDIF IF MODE == 1 store_tail_func_1: cjne Temp4, #1, store_tail_func_2 mov Temp2, #Pgm_Motor_Gain store_tail_func_2: cjne Temp4, #2, store_tail_func_3 mov Temp2, #Pgm_Motor_Idle store_tail_func_3: cjne Temp4, #3, store_tail_func_4 mov Temp2, #Pgm_Startup_Pwr store_tail_func_4: cjne Temp4, #4, store_tail_func_5 mov Temp2, #Pgm_Comm_Timing store_tail_func_5: cjne Temp4, #5, store_tail_func_6 mov Temp2, #Pgm_Pwm_Freq store_tail_func_6: cjne Temp4, #6, store_tail_func_7 mov Temp2, #Pgm_Demag_Comp store_tail_func_7: cjne Temp4, #7, store_tail_func_8 mov Temp2, #Pgm_Direction store_tail_func_8: cjne Temp4, #8, store_in_ram_exit mov Temp2, #Pgm_Input_Pol ENDIF IF MODE == 2 ;store_multi_func_1: ; cjne Temp4, #1, store_multi_func_2 ; mov Temp2, #Pgm_Gov_P_Gain ;store_multi_func_2: ; cjne Temp4, #2, store_multi_func_3 ; mov Temp2, #Pgm_Gov_I_Gain ;store_multi_func_3: ; cjne Temp4, #3, store_multi_func_4 ; mov Temp2, #Pgm_Gov_Mode ;store_multi_func_4: ; cjne Temp4, #4, store_multi_func_5 ; mov Temp2, #Pgm_Motor_Gain ;store_multi_func_5: ; cjne Temp4, #5, store_multi_func_6 ; mov Temp2, #Pgm_Low_Voltage_Lim ;store_multi_func_6: ; cjne Temp4, #6, store_multi_func_7 ; mov Temp2, #Pgm_Startup_Pwr ;store_multi_func_7: ; cjne Temp4, #7, store_multi_func_8 ; mov Temp2, #Pgm_Comm_Timing ;store_multi_func_8: ; cjne Temp4, #8, store_multi_func_9 ; mov Temp2, #Pgm_Pwm_Freq ;store_multi_func_9: ; cjne Temp4, #9, store_multi_func_10 ; mov Temp2, #Pgm_Demag_Comp ;store_multi_func_10: ; cjne Temp4, #10, store_multi_func_11 ; mov Temp2, #Pgm_Direction ;store_multi_func_11: ; cjne Temp4, #11, store_in_ram_exit ; mov Temp2, #Pgm_Input_Pol store_multi_func_1: cjne Temp4, #1, store_multi_func_2 mov Temp2, #Pgm_Damping_Force ;读取Damping force(刹车力度)地址 store_multi_func_2: cjne Temp4, #2, store_multi_func_3 mov Temp2, #Pgm_Comm_Timing ;读取Commutation timing(进角)地址 ;store_multi_func_3: ; cjne Temp4, #3, store_multi_func_4 ; mov Temp2, #Pgm_Direction_Rev ;读取Rotation direction(旋转方式)地址 store_multi_func_3: cjne Temp4, #3, store_multi_func_4 mov Temp2, #Pgm_Startup_Pwr ;读取Startup power(启动力度)地址 store_multi_func_4: cjne Temp4, #4, store_multi_func_5 mov Temp2, #Pgm_Gov_Mode ;读取Closed loop mode(曲线)地址 store_multi_func_5: cjne Temp4, #5, store_multi_func_6 mov Temp2, #Pgm_Pwm_Freq ;读取Startup method(启动方式)地址 store_multi_func_6: cjne Temp4, #6, store_multi_func_7 mov Temp2, #Pgm_Low_Voltage_Lim ;读取Low voltage limit(低压保护)地址 store_multi_func_7: cjne Temp4, #7, store_multi_func_8 mov Temp2, #Pgm_Low_Voltage_Ctl ;读取Low voltage limit(低压保护)地址 store_multi_func_8: cjne Temp4, #8, store_in_ram_exit mov Temp2, #Pgm_Direction ENDIF store_in_ram_exit: mov A, Temp1 mov @Temp2, A ret ;**** **** **** **** **** **** **** **** **** **** **** **** **** ; ; Program by TX routine ; ; No assumptions ; ;**** **** **** **** **** **** **** **** **** **** **** **** **** program_by_tx: ; Programming mode entry beeps call success_beep setb Flags1.PROGRAM_FUNC_FLAG ;编程功能标志 wait_for_program: mov Temp5, #10 default_set_check: call wait200ms clr C mov A, New_Rcp ; Load new RC pulse value subb A, #RCP_STOP ; Below stop? jc wait_for_next_status clr C mov A, New_Rcp ; Load new RC pulse value subb A, #RCP_MAX ; Below max? jc wait_for_program djnz Temp5, default_set_check ;等待进入新设置 ajmp function_no_entry wait_for_next_status: mov Temp5, #10 wait_for_exit: call wait200ms clr C mov A, New_Rcp ; Load new RC pulse value subb A, #RCP_STOP ; Below stop? jnc ($+7) djnz Temp5, wait_for_exit ajmp program_exit clr C mov A, New_Rcp ; Load new RC pulse value subb A, #RCP_MAX ; Below max? jc wait_for_next_status call set_default_parameters ; Load all defaults call erase_and_store_all_in_eeprom ; Erase flash and program call success_beep_inverted ajmp wait_for_program ; Start at function 1, parameter value 1 function_no_entry: mov Tx_Pgm_Func_No, #1 function_no_beep: call function_paraval_beep mov Temp5, #10 ; Wait is 5x 200ms function_no_wait: mov Temp6, New_Rcp call wait200ms clr C mov A, Temp6 subb A, New_Rcp jnz function_no_wait ; No - branch clr C mov A, New_Rcp ; Load new RC pulse value subb A, #RCP_STOP ; Below stop? jc paraval_no_wait clr C mov A, New_Rcp ; Load new RC pulse value subb A, #RCP_MAX ; Below max? jnc function_no_next ajmp function_no_wait ;等待摇杆拉高或拉低 function_no_next: ; Yes - Next function value jnb Flags1.PROGRAM_FUNC_FLAG, func_paraval_store ;=0,则存储参数 djnz Temp5,function_no_wait inc Tx_Pgm_Func_No ; Function value no 功能+1 clr C mov A,Tx_Pgm_Func_No IF MODE == 0 subb A,#12 ENDIF IF MODE >= 1 subb A,#9 ENDIF jc function_no_beep mov Temp5, #10 func_over_wait: call wait200ms clr C mov A, New_Rcp subb A, #RCP_STOP jc program_by_tx_exit ;below stop---exit clr C mov A, New_Rcp subb A, #RCP_MAX jc func_over_wait ;等待摇杆拉高或拉低 djnz Temp5, func_over_wait ; 摇杆一直处于拉高,等待2s结束 ajmp function_no_entry ;返回从第一项开始 func_paraval_store: setb Flags1.PROGRAM_FUNC_FLAG ;编程功能标志 call store_new_value_in_ram ; Yes - store new value in RAM call erase_and_store_all_in_eeprom ; Store all values in EEPROM call success_beep_inverted ; Beep success 改变存储叫声 mov Temp5, #10 ;存储完后等待时间 store_wait: ; call wait200ms clr C mov A, New_Rcp subb A, #RCP_STOP jc program_by_tx_exit ; clr C mov A, New_Rcp ; Load new RC pulse value subb A, #RCP_MAX ; Below max? jc store_wait djnz Temp5, store_wait ;摇杆一直处于拉高状态,等待2s结束 mov Temp5, #1 ajmp function_no_next paraval_no_wait: mov Temp5, #10 ;10*200=1s时间 paraval_wait: call wait200ms clr C mov A, New_Rcp ; Load new RC pulse value subb A, #RCP_MAX ; Below max? jnc function_no_wait clr C mov A, New_Rcp subb A, #RCP_STOP ; Below stop? jnc paraval_wait ;等待摇杆拉高或拉低 djnz Temp5,paraval_wait ; 摇杆一直处于拉低,等待1s结束 clr Flags1.PROGRAM_FUNC_FLAG ;保存标志 paraval_no_entry: mov Tx_Pgm_Paraval_No, #1 paraval_no_beep: call function_paraval_beep mov Temp5, #10 paraval_no_next: call wait200ms clr C mov A, New_Rcp ; Load new RC pulse value subb A, #RCP_MAX ; Below max? jnc function_no_next ; Yes - branch 跳回项目编程 clr C mov A, New_Rcp subb A, #RCP_STOP ; Below stop? jnc paraval_no_next ;等待摇杆拉高或拉低 djnz Temp5, paraval_no_next ; 摇杆一直处于拉低,等待1s结束 inc Tx_Pgm_Paraval_No ; Function value no 参数+1 mov A, Tx_Pgm_Func_No ; Decode number of parameters dec A IF MODE == 0 mov DPTR, #TX_PGM_PARAMS_MAIN ENDIF IF MODE == 1 mov DPTR, #TX_PGM_PARAMS_TAIL ENDIF IF MODE == 2 mov DPTR, #TX_PGM_PARAMS_MULTI ENDIF movc A, @A+DPTR mov Temp1, A inc Temp1 clr C mov A, Tx_Pgm_Paraval_No subb A, Temp1 jnc paraval_no_entry ; Last parameter value? ajmp paraval_no_beep ; No - go back program_by_tx_exit: mov Temp5, #10 ;10*200=2s时间 exit_wait: call wait200ms clr C mov A, New_Rcp subb A, #RCP_STOP ; Below stop? jnc exit_wait ;等待退出 djnz Temp5,exit_wait program_exit: ret