Fork from bluejay at github and modified for my custom ESC. I need to modify it because some mistake design on my ESC hardware.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

3864 lines
102 KiB

  1. $NOMOD51
  2. ;**** **** **** **** ****
  3. ;
  4. ; Bluejay digital ESC firmware for controlling brushless motors in multirotors
  5. ;
  6. ; Copyright 2020 Mathias Rasmussen
  7. ; Copyright 2011, 2012 Steffen Skaug
  8. ;
  9. ; This file is part of Bluejay.
  10. ;
  11. ; Bluejay is free software: you can redistribute it and/or modify
  12. ; it under the terms of the GNU General Public License as published by
  13. ; the Free Software Foundation, either version 3 of the License, or
  14. ; (at your option) any later version.
  15. ;
  16. ; Bluejay is distributed in the hope that it will be useful,
  17. ; but WITHOUT ANY WARRANTY; without even the implied warranty of
  18. ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  19. ; GNU General Public License for more details.
  20. ;
  21. ; You should have received a copy of the GNU General Public License
  22. ; along with Bluejay. If not, see <http://www.gnu.org/licenses/>.
  23. ;
  24. ;**** **** **** **** ****
  25. ;
  26. ; Bluejay is a fork of BLHeli_S <https://github.com/bitdump/BLHeli> by Steffen Skaug.
  27. ;
  28. ; The input signal can be DShot with rates: DShot150, DShot300 and DShot600.
  29. ;
  30. ; This file is best viewed with tab width set to 5.
  31. ;
  32. ;**** **** **** **** ****
  33. ; Master clock is internal 24MHz oscillator (or 48MHz, for which the times below are halved)
  34. ; Although 24/48 are used in the code, the exact clock frequencies are 24.5MHz or 49.0 MHz
  35. ; Timer 0 (41.67ns counts) always counts up and is used for
  36. ; - RC pulse measurement
  37. ; - DShot telemetry signal
  38. ; Timer 1 (41.67ns counts) always counts up and is used for
  39. ; - DShot frame sync detection
  40. ; Timer 2 (500ns counts) always counts up and is used for
  41. ; - RC pulse timeout counts and commutation times
  42. ; Timer 3 (500ns counts) always counts up and is used for
  43. ; - Commutation timeouts
  44. ; PCA0 (41.67ns counts) always counts up and is used for
  45. ; - Hardware PWM generation
  46. ;
  47. ;**** **** **** **** ****
  48. ; Motor control:
  49. ; - Brushless motor control with 6 states for each electrical 360 degrees
  50. ; - An advance timing of 0deg has zero cross 30deg after one commutation and 30deg before the next
  51. ; - Timing advance in this implementation is set to 15deg nominally
  52. ; - Motor pwm is always damped light (aka complementary pwm, regenerative braking)
  53. ; Motor sequence starting from zero crossing:
  54. ; - Timer wait: Wt_Comm 15deg ; Time to wait from zero cross to actual commutation
  55. ; - Timer wait: Wt_Advance 15deg ; Time to wait for timing advance. Nominal commutation point is after this
  56. ; - Timer wait: Wt_Zc_Scan 7.5deg ; Time to wait before looking for zero cross
  57. ; - Scan for zero cross 22.5deg ; Nominal, with some motor variations
  58. ;
  59. ; Motor startup:
  60. ; There is a startup phase and an initial run phase, before normal bemf commutation run begins.
  61. ;
  62. ;**** **** **** **** ****
  63. ; List of enumerated supported ESCs
  64. A_ EQU 1 ; X X RC X MC MB MA CC X X Cc Cp Bc Bp Ac Ap
  65. B_ EQU 2 ; X X RC X MC MB MA CC X X Ap Ac Bp Bc Cp Cc
  66. C_ EQU 3 ; Ac Ap MC MB MA CC X RC X X X X Cc Cp Bc Bp
  67. D_ EQU 4 ; X X RC X CC MA MC MB X X Cc Cp Bc Bp Ac Ap Com fets inverted
  68. E_ EQU 5 ; L1 L0 RC X MC MB MA CC X L2 Cc Cp Bc Bp Ac Ap A with LEDs
  69. F_ EQU 6 ; X X RC X MA MB MC CC X X Cc Cp Bc Bp Ac Ap
  70. G_ EQU 7 ; X X RC X CC MA MC MB X X Cc Cp Bc Bp Ac Ap Like D, but noninverted com fets
  71. H_ EQU 8 ; RC X X X MA MB CC MC X Ap Bp Cp X Ac Bc Cc
  72. I_ EQU 9 ; X X RC X MC MB MA CC X X Ac Bc Cc Ap Bp Cp
  73. J_ EQU 10 ; L2 L1 L0 RC CC MB MC MA X X Cc Bc Ac Cp Bp Ap LEDs
  74. K_ EQU 11 ; X X MC X MB CC MA RC X X Ap Bp Cp Cc Bc Ac Com fets inverted
  75. L_ EQU 12 ; X X RC X CC MA MB MC X X Ac Bc Cc Ap Bp Cp
  76. M_ EQU 13 ; MA MC CC MB RC L0 X X X Cc Bc Ac Cp Bp Ap X LED
  77. N_ EQU 14 ; X X RC X MC MB MA CC X X Cp Cc Bp Bc Ap Ac
  78. O_ EQU 15 ; X X RC X CC MA MC MB X X Cc Cp Bc Bp Ac Ap Like D, but low side pwm
  79. P_ EQU 16 ; X X RC MA CC MB MC X X Cc Bc Ac Cp Bp Ap X
  80. Q_ EQU 17 ; Cp Bp Ap L1 L0 X RC X X MA MB MC CC Cc Bc Ac LEDs
  81. R_ EQU 18 ; X X RC X MC MB MA CC X X Ac Bc Cc Ap Bp Cp
  82. S_ EQU 19 ; X X RC X CC MA MC MB X X Cc Cp Bc Bp Ac Ap Like O, but com fets inverted
  83. T_ EQU 20 ; RC X MA X MB CC MC X X X Cp Bp Ap Ac Bc Cc
  84. U_ EQU 21 ; MA MC CC MB RC L0 L1 L2 X Cc Bc Ac Cp Bp Ap X Like M, but with 3 LEDs
  85. V_ EQU 22 ; Cc X RC X MC CC MB MA X Ap Ac Bp X X Bc Cp
  86. W_ EQU 23 ; RC MC MB X CC MA X X X Ap Bp Cp X X X X Tristate gate driver
  87. ;**** **** **** **** ****
  88. ; Select the port mapping to use (or unselect all for use with external batch compile file)
  89. ;ESCNO EQU A_
  90. ;**** **** **** **** ****
  91. ; Select the MCU type (or unselect for use with external batch compile file)
  92. ;MCU_48MHZ EQU 0
  93. ;**** **** **** **** ****
  94. ; Select the fet deadtime (or unselect for use with external batch compile file)
  95. ;FETON_DELAY EQU 15 ; 20.4ns per step
  96. ;**** **** **** **** ****
  97. ; Select the pwm frequency (or unselect for use with external batch compile file)
  98. ;PWM_FREQ EQU 0 ; 0=24, 1=48, 2=96 kHz
  99. $include (Common.inc) ; Include common source code for EFM8BBx based ESCs
  100. ;**** **** **** **** ****
  101. ; Programming defaults
  102. ;
  103. DEFAULT_PGM_STARTUP_PWR EQU 9 ; 1=0.031 2=0.047 3=0.063 4=0.094 5=0.125 6=0.188 7=0.25 8=0.38 9=0.50 10=0.75 11=1.00 12=1.25 13=1.50
  104. DEFAULT_PGM_COMM_TIMING EQU 3 ; 1=Low 2=MediumLow 3=Medium 4=MediumHigh 5=High
  105. DEFAULT_PGM_DEMAG_COMP EQU 2 ; 1=Disabled 2=Low 3=High
  106. DEFAULT_PGM_DIRECTION EQU 1 ; 1=Normal 2=Reversed 3=Bidir 4=Bidir rev
  107. DEFAULT_PGM_BEEP_STRENGTH EQU 40 ; Beep strength
  108. DEFAULT_PGM_BEACON_STRENGTH EQU 80 ; Beacon strength
  109. DEFAULT_PGM_BEACON_DELAY EQU 4 ; 1=1m 2=2m 3=5m 4=10m 5=Infinite
  110. ; COMMON
  111. DEFAULT_PGM_ENABLE_TEMP_PROT EQU 7 ; 0=Disabled 1=80C 2=90C 3=100C 4=110C 5=120C 6=130C 7=140C
  112. DEFAULT_PGM_ENABLE_POWER_PROT EQU 1 ; 1=Enabled 0=Disabled
  113. DEFAULT_PGM_BRAKE_ON_STOP EQU 0 ; 1=Enabled 0=Disabled
  114. DEFAULT_PGM_LED_CONTROL EQU 0 ; Byte for LED control. 2bits per LED, 0=Off, 1=On
  115. ;**** **** **** **** ****
  116. ; Temporary register definitions
  117. Temp1 EQU R0
  118. Temp2 EQU R1
  119. Temp3 EQU R2
  120. Temp4 EQU R3
  121. Temp5 EQU R4
  122. Temp6 EQU R5
  123. Temp7 EQU R6
  124. Temp8 EQU R7
  125. ;**** **** **** **** ****
  126. ; RAM definitions
  127. DSEG AT 20h ; Ram data segment, bit-addressable
  128. Bit_Access: DS 1 ; MUST BE AT THIS ADDRESS. Variable at bit accessible address (for non interrupt routines)
  129. Bit_Access_Int: DS 1 ; Variable at bit accessible address (for interrupts)
  130. Rcp_Outside_Range_Cnt: DS 1 ; RC pulse outside range counter (incrementing)
  131. Rcp_Timeout_Cntd: DS 1 ; RC pulse timeout counter (decrementing)
  132. Flags0: DS 1 ; State flags. Reset upon init_start
  133. Flag_T3_PENDING BIT Flags0.0 ; Timer 3 pending flag
  134. Flag_DEMAG_DETECTED BIT Flags0.1 ; Set when excessive demag time is detected
  135. Flag_COMP_TIMED_OUT BIT Flags0.2 ; Set when comparator reading timed out
  136. Flag_PACKET_PENDING BIT Flags0.4 ; DShot telemetry data packet is ready to be sent
  137. Flags1: DS 1 ; State flags. Reset upon init_start
  138. Flag_MOTOR_STARTED BIT Flags1.2 ; Set when motor is started
  139. Flag_DIR_CHANGE_BRAKE BIT Flags1.3 ; Set when braking before direction change
  140. Flag_HIGH_RPM BIT Flags1.4 ; Set when motor rpm is high (Comm_Period4x_H less than 2)
  141. Flag_LOW_PWM_POWER BIT Flags1.5 ; Set when pwm duty cycle is below 50%
  142. Flags_Startup: DS 1 ; State flags. Reset upon init_start
  143. Flag_STARTUP_PHASE BIT Flags_Startup.0 ; Set when in startup phase
  144. Flag_INITIAL_RUN_PHASE BIT Flags_Startup.1 ; Set when in initial run phase, before synchronized run is achieved
  145. ; Remaining bits must be cleared
  146. Flags2: DS 1 ; State flags. NOT reset upon init_start
  147. Flag_RCP_DIR_REV BIT Flags2.5 ; RC pulse direction in bidirectional mode
  148. Flag_RCP_DSHOT_INVERTED BIT Flags2.7 ; DShot RC pulse input is inverted (and supports telemetry)
  149. Flags3: DS 1 ; State flags. NOT reset upon init_start
  150. Flag_PGM_DIR_REV BIT Flags3.0 ; Programmed direction. 0=normal, 1=reversed
  151. Flag_PGM_BIDIR_REV BIT Flags3.1 ; Programmed bidirectional direction. 0=normal, 1=reversed
  152. Flag_PGM_BIDIR BIT Flags3.2 ; Programmed bidirectional operation. 0=normal, 1=bidirectional
  153. Flag_SKIP_T2_INT BIT Flags3.3 ; Set for 48MHz MCUs when timer 2 interrupt shall be ignored
  154. Flag_CLOCK_SET_AT_48MHZ BIT Flags3.4 ; Set if 48MHz MCUs run at 48MHz
  155. Flag_RCP_STOP BIT Flags3.5 ; Set if the RC pulse value is zero
  156. Tlm_Data_L: DS 1 ; DShot telemetry data low byte
  157. Tlm_Data_H: DS 1 ; DShot telemetry data high byte
  158. Tmp_B: DS 1
  159. DSEG AT 30h ; Ram data segment, direct addressing
  160. Power_On_Wait_Cnt_L: DS 1 ; Power on wait counter (lo byte)
  161. Power_On_Wait_Cnt_H: DS 1 ; Power on wait counter (hi byte)
  162. Startup_Cnt: DS 1 ; Startup phase commutations counter (incrementing)
  163. Startup_Zc_Timeout_Cntd: DS 1 ; Startup zero cross timeout counter (decrementing)
  164. Initial_Run_Rot_Cntd: DS 1 ; Initial run rotations counter (decrementing)
  165. Stall_Cnt: DS 1 ; Counts start/run attempts that resulted in stall. Reset upon a proper stop
  166. Demag_Detected_Metric: DS 1 ; Metric used to gauge demag event frequency
  167. Demag_Pwr_Off_Thresh: DS 1 ; Metric threshold above which power is cut
  168. Low_Rpm_Pwr_Slope: DS 1 ; Sets the slope of power increase for low rpms
  169. Timer2_X: DS 1 ; Timer 2 extended byte
  170. Prev_Comm_L: DS 1 ; Previous commutation timer 3 timestamp (lo byte)
  171. Prev_Comm_H: DS 1 ; Previous commutation timer 3 timestamp (hi byte)
  172. Prev_Comm_X: DS 1 ; Previous commutation timer 3 timestamp (ext byte)
  173. Prev_Prev_Comm_L: DS 1 ; Pre-previous commutation timer 3 timestamp (lo byte)
  174. Prev_Prev_Comm_H: DS 1 ; Pre-previous commutation timer 3 timestamp (hi byte)
  175. Comm_Period4x_L: DS 1 ; Timer 3 counts between the last 4 commutations (lo byte)
  176. Comm_Period4x_H: DS 1 ; Timer 3 counts between the last 4 commutations (hi byte)
  177. Comparator_Read_Cnt: DS 1 ; Number of comparator reads done
  178. Wt_Adv_Start_L: DS 1 ; Timer 3 start point for commutation advance timing (lo byte)
  179. Wt_Adv_Start_H: DS 1 ; Timer 3 start point for commutation advance timing (hi byte)
  180. Wt_Zc_Scan_Start_L: DS 1 ; Timer 3 start point from commutation to zero cross scan (lo byte)
  181. Wt_Zc_Scan_Start_H: DS 1 ; Timer 3 start point from commutation to zero cross scan (hi byte)
  182. Wt_Zc_Tout_Start_L: DS 1 ; Timer 3 start point for zero cross scan timeout (lo byte)
  183. Wt_Zc_Tout_Start_H: DS 1 ; Timer 3 start point for zero cross scan timeout (hi byte)
  184. Wt_Comm_Start_L: DS 1 ; Timer 3 start point from zero cross to commutation (lo byte)
  185. Wt_Comm_Start_H: DS 1 ; Timer 3 start point from zero cross to commutation (hi byte)
  186. Dshot_Cmd: DS 1 ; DShot command
  187. Dshot_Cmd_Cnt: DS 1 ; DShot command count
  188. Rcp_Stop_Cnt: DS 1 ; Counter for RC pulses below stop value
  189. Power_Pwm_Reg_L: DS 1 ; Power pwm register setting (lo byte)
  190. Power_Pwm_Reg_H: DS 1 ; Power pwm register setting (hi byte). 0x3F is minimum power
  191. Damp_Pwm_Reg_L: DS 1 ; Damping pwm register setting (lo byte)
  192. Damp_Pwm_Reg_H: DS 1 ; Damping pwm register setting (hi byte)
  193. Pwm_Limit: DS 1 ; Maximum allowed pwm
  194. Pwm_Limit_By_Rpm: DS 1 ; Maximum allowed pwm for low or high rpms
  195. Pwm_Limit_Beg: DS 1 ; Initial pwm limit
  196. Adc_Conversion_Cnt: DS 1 ; Adc conversion counter
  197. Current_Average_Temp: DS 1 ; Current average temperature (lo byte ADC reading, assuming hi byte is 1)
  198. Beep_Strength: DS 1 ; Strength of beeps
  199. Flash_Key_1: DS 1 ; Flash key one
  200. Flash_Key_2: DS 1 ; Flash key two
  201. Temp_Prot_Limit: DS 1 ; Temperature protection limit
  202. DShot_Pwm_Thr: DS 1 ; DShot pulse width threshold value
  203. DShot_Timer_Preset: DS 1 ; DShot timer preset for frame sync detection
  204. DShot_Frame_Start_L: DS 1 ; DShot frame start timestamp (lo byte)
  205. DShot_Frame_Start_H: DS 1 ; DShot frame start timestamp (hi byte)
  206. DShot_Frame_Length_Thr: DS 1 ; DShot frame length criteria (in units of 4 timer 2 ticks)
  207. ; Pulse durations for GCR encoding DShot telemetry data
  208. DShot_GCR_Pulse_Time_1: DS 1 ; Encodes binary: 1
  209. DShot_GCR_Pulse_Time_2: DS 1 ; Encodes binary: 01
  210. DShot_GCR_Pulse_Time_3: DS 1 ; Encodes binary: 001
  211. DShot_GCR_Pulse_Time_1_Tmp: DS 1
  212. DShot_GCR_Pulse_Time_2_Tmp: DS 1
  213. DShot_GCR_Pulse_Time_3_Tmp: DS 1
  214. DShot_GCR_Start_Delay: DS 1
  215. ; Indirect addressing data segment. The variables below must be in this sequence
  216. ISEG AT 080h
  217. _Pgm_Gov_P_Gain: DS 1 ; Governor P gain
  218. _Pgm_Gov_I_Gain: DS 1 ; Governor I gain
  219. _Pgm_Gov_Mode: DS 1 ; Governor mode
  220. _Pgm_Low_Voltage_Lim: DS 1 ; Low voltage limit
  221. _Pgm_Motor_Gain: DS 1 ; Motor gain
  222. _Pgm_Motor_Idle: DS 1 ; Motor idle speed
  223. Pgm_Startup_Pwr: DS 1 ; Startup power
  224. _Pgm_Pwm_Freq: DS 1 ; PWM frequency
  225. Pgm_Direction: DS 1 ; Rotation direction
  226. _Pgm_Input_Pol: DS 1 ; Input PWM polarity
  227. Initialized_L_Dummy: DS 1 ; Place holder
  228. Initialized_H_Dummy: DS 1 ; Place holder
  229. _Pgm_Enable_TX_Program: DS 1 ; Enable/disable value for TX programming
  230. _Pgm_Main_Rearm_Start: DS 1 ; Enable/disable re-arming main every start
  231. _Pgm_Gov_Setup_Target: DS 1 ; Main governor setup target
  232. _Pgm_Startup_Rpm: DS 1 ; Startup RPM
  233. _Pgm_Startup_Accel: DS 1 ; Startup acceleration
  234. _Pgm_Volt_Comp: DS 1 ; Voltage comp
  235. Pgm_Comm_Timing: DS 1 ; Commutation timing
  236. _Pgm_Damping_Force: DS 1 ; Damping force
  237. _Pgm_Gov_Range: DS 1 ; Governor range
  238. _Pgm_Startup_Method: DS 1 ; Startup method
  239. _Pgm_Min_Throttle: DS 1 ; Minimum throttle
  240. _Pgm_Max_Throttle: DS 1 ; Maximum throttle
  241. Pgm_Beep_Strength: DS 1 ; Beep strength
  242. Pgm_Beacon_Strength: DS 1 ; Beacon strength
  243. Pgm_Beacon_Delay: DS 1 ; Beacon delay
  244. _Pgm_Throttle_Rate: DS 1 ; Throttle rate
  245. Pgm_Demag_Comp: DS 1 ; Demag compensation
  246. _Pgm_BEC_Voltage_High: DS 1 ; BEC voltage
  247. _Pgm_Center_Throttle: DS 1 ; Center throttle (in bidirectional mode)
  248. _Pgm_Main_Spoolup_Time: DS 1 ; Main spoolup time
  249. Pgm_Enable_Temp_Prot: DS 1 ; Temperature protection enable
  250. Pgm_Enable_Power_Prot: DS 1 ; Low RPM power protection enable
  251. _Pgm_Enable_Pwm_Input: DS 1 ; Enable PWM input signal
  252. _Pgm_Pwm_Dither: DS 1 ; Output PWM dither
  253. Pgm_Brake_On_Stop: DS 1 ; Braking when throttle is zero
  254. Pgm_LED_Control: DS 1 ; LED control
  255. ; The sequence of the variables below is no longer of importance
  256. Pgm_Startup_Pwr_Decoded: DS 1 ; Programmed startup power decoded
  257. ; Indirect addressing data segments
  258. ISEG AT 0B0h
  259. Stack: DS 16 ; Reserved stack space
  260. ISEG AT 0C0h
  261. Dithering_Patterns: DS 16
  262. ISEG AT 0D0h
  263. Temp_Storage: DS 48 ; Temporary storage
  264. ;**** **** **** **** ****
  265. CSEG AT 1A00h ; "Eeprom" segment
  266. EEPROM_FW_MAIN_REVISION EQU 0 ; Main revision of the firmware
  267. EEPROM_FW_SUB_REVISION EQU 40 ; Sub revision of the firmware
  268. EEPROM_LAYOUT_REVISION EQU 33 ; Revision of the EEPROM layout
  269. Eep_FW_Main_Revision: DB EEPROM_FW_MAIN_REVISION ; EEPROM firmware main revision number
  270. Eep_FW_Sub_Revision: DB EEPROM_FW_SUB_REVISION ; EEPROM firmware sub revision number
  271. Eep_Layout_Revision: DB EEPROM_LAYOUT_REVISION ; EEPROM layout revision number
  272. _Eep_Pgm_Gov_P_Gain: DB 0FFh
  273. _Eep_Pgm_Gov_I_Gain: DB 0FFh
  274. _Eep_Pgm_Gov_Mode: DB 0FFh
  275. _Eep_Pgm_Low_Voltage_Lim: DB 0FFh
  276. _Eep_Pgm_Motor_Gain: DB 0FFh
  277. _Eep_Pgm_Motor_Idle: DB 0FFh
  278. Eep_Pgm_Startup_Pwr: DB DEFAULT_PGM_STARTUP_PWR ; EEPROM copy of programmed startup power
  279. _Eep_Pgm_Pwm_Freq: DB 0FFh
  280. Eep_Pgm_Direction: DB DEFAULT_PGM_DIRECTION ; EEPROM copy of programmed rotation direction
  281. _Eep__Pgm_Input_Pol: DB 0FFh
  282. Eep_Initialized_L: DB 055h ; EEPROM initialized signature low byte
  283. Eep_Initialized_H: DB 0AAh ; EEPROM initialized signature high byte
  284. _Eep_Enable_TX_Program: DB 0FFh ; EEPROM TX programming enable
  285. _Eep_Main_Rearm_Start: DB 0FFh
  286. _Eep_Pgm_Gov_Setup_Target: DB 0FFh
  287. _Eep_Pgm_Startup_Rpm: DB 0FFh
  288. _Eep_Pgm_Startup_Accel: DB 0FFh
  289. _Eep_Pgm_Volt_Comp: DB 0FFh
  290. Eep_Pgm_Comm_Timing: DB DEFAULT_PGM_COMM_TIMING ; EEPROM copy of programmed commutation timing
  291. _Eep_Pgm_Damping_Force: DB 0FFh
  292. _Eep_Pgm_Gov_Range: DB 0FFh
  293. _Eep_Pgm_Startup_Method: DB 0FFh
  294. _Eep_Pgm_Min_Throttle: DB 0FFh ; EEPROM copy of programmed minimum throttle
  295. _Eep_Pgm_Max_Throttle: DB 0FFh ; EEPROM copy of programmed minimum throttle
  296. Eep_Pgm_Beep_Strength: DB DEFAULT_PGM_BEEP_STRENGTH ; EEPROM copy of programmed beep strength
  297. Eep_Pgm_Beacon_Strength: DB DEFAULT_PGM_BEACON_STRENGTH ; EEPROM copy of programmed beacon strength
  298. Eep_Pgm_Beacon_Delay: DB DEFAULT_PGM_BEACON_DELAY ; EEPROM copy of programmed beacon delay
  299. _Eep_Pgm_Throttle_Rate: DB 0FFh
  300. Eep_Pgm_Demag_Comp: DB DEFAULT_PGM_DEMAG_COMP ; EEPROM copy of programmed demag compensation
  301. _Eep_Pgm_BEC_Voltage_High: DB 0FFh
  302. _Eep_Pgm_Center_Throttle: DB 0FFh ; EEPROM copy of programmed center throttle
  303. _Eep_Pgm_Main_Spoolup_Time: DB 0FFh
  304. Eep_Pgm_Temp_Prot_Enable: DB DEFAULT_PGM_ENABLE_TEMP_PROT ; EEPROM copy of programmed temperature protection enable
  305. Eep_Pgm_Enable_Power_Prot: DB DEFAULT_PGM_ENABLE_POWER_PROT ; EEPROM copy of programmed low rpm power protection enable
  306. _Eep_Pgm_Enable_Pwm_Input: DB 0FFh
  307. _Eep_Pgm_Pwm_Dither: DB 0FFh
  308. Eep_Pgm_Brake_On_Stop: DB DEFAULT_PGM_BRAKE_ON_STOP ; EEPROM copy of programmed braking when throttle is zero
  309. Eep_Pgm_LED_Control: DB DEFAULT_PGM_LED_CONTROL ; EEPROM copy of programmed LED control
  310. Eep_Dummy: DB 0FFh ; EEPROM address for safety reason
  311. CSEG AT 1A60h
  312. Eep_Name: DB "Bluejay (BETA) " ; Name tag (16 Bytes)
  313. ;**** **** **** **** ****
  314. ; DShot Telemetry Macros
  315. DSHOT_TLM_CLOCK EQU 24500000 ; 24.5MHz
  316. DSHOT_TLM_START_DELAY EQU -1 ; Start telemetry after 1 tick (~30us after receiving DShot cmd)
  317. DSHOT_TLM_PREDELAY EQU 6 ; 6 timer 0 ticks inherent delay
  318. IF MCU_48MHZ == 1
  319. DSHOT_TLM_CLOCK_48 EQU 49000000 ; 49MHz
  320. DSHOT_TLM_START_DELAY_48 EQU -(14 * 49 / 4) ; Start telemetry after 14us (~30us after receiving DShot cmd)
  321. DSHOT_TLM_PREDELAY_48 EQU 8 ; 8 timer 0 ticks inherent delay
  322. ENDIF
  323. Set_DShot_Tlm_Bitrate MACRO rate
  324. mov DShot_GCR_Pulse_Time_1, #(DSHOT_TLM_PREDELAY - (1 * DSHOT_TLM_CLOCK / 4 / rate))
  325. mov DShot_GCR_Pulse_Time_2, #(DSHOT_TLM_PREDELAY - (2 * DSHOT_TLM_CLOCK / 4 / rate))
  326. mov DShot_GCR_Pulse_Time_3, #(DSHOT_TLM_PREDELAY - (3 * DSHOT_TLM_CLOCK / 4 / rate))
  327. mov DShot_GCR_Start_Delay, #DSHOT_TLM_START_DELAY
  328. IF MCU_48MHZ == 1
  329. mov DShot_GCR_Pulse_Time_1_Tmp, #(DSHOT_TLM_PREDELAY_48 - (1 * DSHOT_TLM_CLOCK_48 / 4 / rate))
  330. mov DShot_GCR_Pulse_Time_2_Tmp, #(DSHOT_TLM_PREDELAY_48 - (2 * DSHOT_TLM_CLOCK_48 / 4 / rate))
  331. mov DShot_GCR_Pulse_Time_3_Tmp, #(DSHOT_TLM_PREDELAY_48 - (3 * DSHOT_TLM_CLOCK_48 / 4 / rate))
  332. ENDIF
  333. ENDM
  334. Push_Mem MACRO reg, val
  335. mov @reg, val ;; Write value to memory address pointed to by register
  336. inc reg ;; Increment pointer
  337. ENDM
  338. DShot_GCR_Get_Time MACRO
  339. mov A, DShot_GCR_Pulse_Time_2
  340. cjne A, Tmp_B, ($+5)
  341. mov A, DShot_GCR_Pulse_Time_3
  342. ENDM
  343. ; Prepare telemetry packet while waiting for timer 3 to wrap
  344. Wait_For_Timer3 MACRO
  345. LOCAL wait_for_t3 done_waiting
  346. jb Flag_PACKET_PENDING, wait_for_t3
  347. jnb Flag_T3_PENDING, done_waiting
  348. call dshot_tlm_create_packet
  349. wait_for_t3:
  350. jnb Flag_T3_PENDING, done_waiting
  351. sjmp wait_for_t3
  352. done_waiting:
  353. ENDM
  354. Early_Return_Packet_Stage MACRO num
  355. Early_Return_Packet_Stage_ num, %(num+1)
  356. ENDM
  357. Early_Return_Packet_Stage_ MACRO num next
  358. IF num > 0
  359. inc Temp5 ;; Increment current packet stage
  360. jb Flag_T3_PENDING, dshot_packet_stage_&num ;; Return early if timer 3 has wrapped
  361. pop PSW
  362. ret
  363. dshot_packet_stage_&num:
  364. ENDIF
  365. IF num < 5
  366. cjne Temp5, #(num), dshot_packet_stage_&next ;; If this is not current stage, skip to next
  367. ENDIF
  368. ENDM
  369. IF FETON_DELAY == 0
  370. PWM_CENTERED EQU 0
  371. ELSE
  372. PWM_CENTERED EQU 1
  373. ENDIF
  374. IF MCU_48MHZ < 2 AND PWM_FREQ < 3
  375. ; Number of bits in pwm high byte
  376. PWM_BITS_H EQU (2 + MCU_48MHZ - PWM_CENTERED - PWM_FREQ)
  377. ENDIF
  378. Decode_DShot_2Bit MACRO dest, decode_fail
  379. movx A, @Temp1
  380. mov Temp7, A
  381. clr C
  382. subb A, Temp6 ; Subtract previous timestamp
  383. clr C
  384. subb A, Temp2
  385. jc decode_fail ; Check that bit is longer than minimum
  386. subb A, Temp2 ; Check if bit is zero or one
  387. mov A, dest ; Shift bit into data byte
  388. rlc A
  389. mov dest, A
  390. inc Temp1 ; Next bit
  391. movx A, @Temp1
  392. mov Temp6, A
  393. clr C
  394. subb A, Temp7
  395. clr C
  396. subb A, Temp2
  397. jc decode_fail
  398. subb A, Temp2
  399. mov A, dest
  400. rlc A
  401. mov dest, A
  402. inc Temp1
  403. ENDM
  404. ;**** **** **** **** ****
  405. Interrupt_Table_Definition ; SiLabs interrupts
  406. CSEG AT 80h ; Code segment after interrupt vectors
  407. ;**** **** **** **** ****
  408. ; Table definitions
  409. STARTUP_POWER_TABLE: DB 1, 2, 3, 4, 6, 9, 12, 18, 25, 37, 50, 62, 75
  410. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  411. ;
  412. ; Timer 0 interrupt routine
  413. ;
  414. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  415. t0_int:
  416. push PSW
  417. mov PSW, #10h ; Select register bank 2 for this interrupt
  418. dec Temp1
  419. cjne Temp1, #(Temp_Storage-1), t0_int_dshot_tlm_transition
  420. ; If last pulse is high telemetry is finished
  421. jb RTX_PORT.RTX_PIN, t0_int_dshot_tlm_finish
  422. inc Temp1 ; Otherwise wait for it to return to high
  423. t0_int_dshot_tlm_transition:
  424. cpl RTX_PORT.RTX_PIN ; Invert signal level
  425. mov TL0, @Temp1 ; Schedule next update
  426. pop PSW
  427. reti
  428. t0_int_dshot_tlm_finish:
  429. ; Configure RTX_PIN for digital input
  430. anl RTX_MDOUT, #(NOT (1 SHL RTX_PIN)) ; Set RTX_PIN output mode to open-drain
  431. setb RTX_PORT.RTX_PIN ; Float high
  432. clr IE_ET0 ; Disable timer 0 interrupts
  433. ; todo: dshot150
  434. ;mov CKCON0, Temp2 ; Restore normal DShot timer 0/1 clock settings
  435. mov CKCON0, #0Ch
  436. mov TMOD, #0AAh ; Timer 0/1 gated by INT0/1
  437. clr TCON_IE0 ; Clear int0 pending flag
  438. clr TCON_IE1 ; Clear int1 pending flag
  439. mov TL0, #0 ; Reset timer 0 count
  440. setb IE_EX0 ; Enable int0 interrupts
  441. setb IE_EX1 ; Enable int1 interrupts
  442. Enable_PCA_Interrupt ; Enable pca interrupts
  443. clr Flag_PACKET_PENDING
  444. pop PSW
  445. reti
  446. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  447. ;
  448. ; Timer 1 interrupt routine
  449. ;
  450. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  451. t1_int:
  452. clr IE_EX0 ; Disable int0 interrupts
  453. clr TCON_TR1 ; Stop timer 1
  454. mov TL1, DShot_Timer_Preset ; Reset sync timer
  455. push PSW
  456. mov PSW, #8h ; Select register bank 1 for this interrupt
  457. push ACC
  458. push B
  459. clr TMR2CN0_TR2 ; Timer 2 disabled
  460. mov Temp2, TMR2L ; Read timer value
  461. mov Temp3, TMR2H
  462. setb TMR2CN0_TR2 ; Timer 2 enabled
  463. ; Check frame time length
  464. clr C
  465. mov A, Temp2
  466. subb A, DShot_Frame_Start_L
  467. mov Temp2, A
  468. mov A, Temp3
  469. subb A, DShot_Frame_Start_H
  470. jnz t1_int_frame_fail ; Frame too long
  471. clr C
  472. mov A, Temp2
  473. subb A, DShot_Frame_Length_Thr
  474. jc t1_int_frame_fail ; Frame too short
  475. subb A, DShot_Frame_Length_Thr
  476. jnc t1_int_frame_fail ; Frame too long
  477. ; Check that correct number of pulses is received
  478. cjne Temp1, #16, t1_int_frame_fail ; Read current pointer
  479. ; Decode transmitted data
  480. mov Temp1, #0 ; Set pointer
  481. mov Temp2, DShot_Pwm_Thr ; DShot pulse width criteria
  482. mov Temp6, #0 ; Reset timestamp
  483. ; Decode DShot data Msb. Use more code space to save time (by not using loop)
  484. Decode_DShot_2Bit Temp5, t1_int_frame_fail
  485. Decode_DShot_2Bit Temp5, t1_int_frame_fail
  486. sjmp t1_int_decode_lsb
  487. t1_int_frame_fail:
  488. sjmp t1_int_outside_range
  489. t1_int_decode_lsb:
  490. ; Decode DShot data Lsb
  491. Decode_DShot_2Bit Temp4, t1_int_outside_range
  492. Decode_DShot_2Bit Temp4, t1_int_outside_range
  493. Decode_DShot_2Bit Temp4, t1_int_outside_range
  494. Decode_DShot_2Bit Temp4, t1_int_outside_range
  495. sjmp t1_int_decode_checksum
  496. t1_int_outside_range:
  497. inc Rcp_Outside_Range_Cnt
  498. mov A, Rcp_Outside_Range_Cnt
  499. jnz ($+4)
  500. dec Rcp_Outside_Range_Cnt
  501. clr C
  502. mov A, Rcp_Outside_Range_Cnt
  503. subb A, #50 ; Allow a given number of outside pulses
  504. jc t1_int_exit_timeout ; If outside limits - ignore first pulses
  505. setb Flag_RCP_STOP ; Set pulse length to zero
  506. clr A
  507. mov Dshot_Cmd, A ; Clear DShot command
  508. mov Dshot_Cmd_Cnt, A ; Clear DShot command count
  509. ajmp t1_int_exit_no_tlm ; Exit without reseting timeout
  510. t1_int_exit_timeout:
  511. mov Rcp_Timeout_Cntd, #10 ; Set timeout count
  512. ajmp t1_int_exit_no_tlm
  513. t1_int_decode_checksum:
  514. ; Decode DShot data checksum
  515. Decode_DShot_2Bit Temp3, t1_int_outside_range
  516. Decode_DShot_2Bit Temp3, t1_int_outside_range
  517. ; XOR check (in inverted data, which is ok), only low nibble is considered
  518. mov A, Temp4
  519. swap A
  520. xrl A, Temp4
  521. xrl A, Temp5
  522. xrl A, Temp3
  523. jnb Flag_RCP_DSHOT_INVERTED, ($+4)
  524. cpl A ; Invert checksum if using inverted DShot
  525. anl A, #0Fh
  526. jnz t1_int_outside_range ; XOR check
  527. ; Invert DShot data and subtract 96 (still 12 bits)
  528. clr C
  529. mov A, Temp4
  530. cpl A
  531. mov Temp3, A
  532. subb A, #96
  533. mov Temp4, A
  534. mov A, Temp5
  535. cpl A
  536. anl A, #0Fh
  537. subb A, #0
  538. mov Temp5, A
  539. jnc t1_normal_range
  540. mov A, Temp3 ; Check for 0 or DShot command
  541. mov Temp5, #0
  542. mov Temp4, #0
  543. jz t1_normal_range
  544. mov Temp3, #0
  545. clr C ; We are in the special DShot range
  546. rrc A ; Divide by 2
  547. jnc t1_dshot_set_cmd ; Check for tlm bit set (if not telemetry, Temp3 will be zero and result in invalid command)
  548. mov Temp3, A
  549. cjne A, Dshot_Cmd, t1_dshot_set_cmd
  550. inc Dshot_Cmd_Cnt
  551. sjmp t1_normal_range
  552. t1_dshot_set_cmd:
  553. mov Dshot_Cmd, Temp3
  554. mov Dshot_Cmd_Cnt, #0
  555. t1_normal_range:
  556. ; Check for bidirectional operation (0=stop, 96-2095->fwd, 2096-4095->rev)
  557. jnb Flag_PGM_BIDIR, t1_int_not_bidir ; If not bidirectional operation - branch
  558. ; Subtract 2000 (still 12 bits)
  559. clr C
  560. mov A, Temp4
  561. subb A, #0D0h
  562. mov B, A
  563. mov A, Temp5
  564. subb A, #07h
  565. clr Flag_RCP_DIR_REV
  566. jc t1_int_bidir_rev_chk ; If result is negative - branch
  567. mov Temp4, B
  568. mov Temp5, A
  569. setb Flag_RCP_DIR_REV
  570. t1_int_bidir_rev_chk:
  571. jb Flag_PGM_BIDIR_REV, ($+5)
  572. cpl Flag_RCP_DIR_REV
  573. clr C ; Multiply throttle value by 2
  574. mov A, Temp4
  575. rlc A
  576. mov Temp4, A
  577. mov A, Temp5
  578. rlc A
  579. mov Temp5, A
  580. t1_int_not_bidir:
  581. ; Generate 4/256
  582. mov A, Temp5
  583. add A, Temp5
  584. addc A, Temp5
  585. addc A, Temp5
  586. mov Temp3, A
  587. ; Align to 11 bits
  588. clr C
  589. mov A, Temp5
  590. rrc A
  591. mov Temp5, A
  592. mov A, Temp4
  593. rrc A
  594. mov Temp4, A
  595. ; Scale from 2000 to 2048
  596. mov A, Temp4
  597. add A, Temp3 ; Holds 4/128
  598. mov Temp4, A
  599. mov A, Temp5
  600. addc A, #0
  601. mov Temp5, A
  602. jnb ACC.3, ($+7)
  603. mov Temp4, #0FFh ; Set maximum 11-bit value
  604. mov Temp5, #07h
  605. ; Boost pwm during direct start
  606. mov A, Flags_Startup
  607. jz t1_int_startup_boosted
  608. jb Flag_MOTOR_STARTED, t1_int_startup_boosted ; Do not boost when changing direction in bidirectional mode
  609. ; Add an extra power boost during start
  610. mov Temp6, Stall_Cnt
  611. inc Temp6
  612. mov B, #31
  613. t1_int_startup_boost_stall:
  614. mov A, Temp4
  615. add A, B
  616. mov Temp4, A
  617. mov A, Temp5
  618. addc A, #0
  619. mov Temp5, A
  620. mov A, B
  621. rl A ; Add more boost when stalling
  622. mov B, A
  623. djnz Temp6, t1_int_startup_boost_stall
  624. jnb ACC.3, ($+7)
  625. mov Temp4, #0FFh ; Set maximum 11-bit value
  626. mov Temp5, #07h
  627. t1_int_startup_boosted:
  628. ; Set 8-bit value
  629. mov A, Temp4
  630. anl A, #0F8h
  631. orl A, Temp5 ; Assumes Temp5 to be 3-bit (11-bit rcp)
  632. swap A
  633. rl A
  634. mov Temp2, A
  635. jnz t1_int_rcp_not_zero
  636. mov A, Temp4 ; New_Rcp (Temp2) is only zero if all 11 bits are zero
  637. jnz t1_int_rcp_not_zero
  638. setb Flag_RCP_STOP
  639. sjmp t1_int_zero_rcp_checked
  640. t1_int_rcp_not_zero:
  641. mov Rcp_Stop_Cnt, #0 ; Reset rcp stop counter
  642. clr Flag_RCP_STOP ; Pulse ready
  643. t1_int_zero_rcp_checked:
  644. ; Decrement outside range counter
  645. mov A, Rcp_Outside_Range_Cnt
  646. jz ($+4)
  647. dec Rcp_Outside_Range_Cnt
  648. ; Set pwm limit
  649. clr C
  650. mov A, Pwm_Limit ; Limit to the smallest
  651. mov Temp6, A ; Store limit in Temp6
  652. subb A, Pwm_Limit_By_Rpm
  653. jc ($+4)
  654. mov Temp6, Pwm_Limit_By_Rpm
  655. ; Check against limit
  656. clr C
  657. mov A, Temp6
  658. subb A, Temp2 ; 8-bit rc pulse
  659. jnc t1_int_scale_pwm_resolution
  660. IF PWM_BITS_H == 0 ; 8-bit pwm
  661. mov A, Temp6
  662. mov Temp2, A
  663. ELSE
  664. mov A, Temp6 ; Multiply limit by 8 for 11-bit pwm
  665. mov B, #8
  666. mul AB
  667. mov Temp4, A
  668. mov Temp5, B
  669. ENDIF
  670. t1_int_scale_pwm_resolution:
  671. ; Scale pwm resolution and invert
  672. IF PWM_BITS_H == 3 ; 11-bit pwm
  673. mov A, Temp5
  674. cpl A
  675. anl A, #7
  676. mov Temp3, A
  677. mov A, Temp4
  678. cpl A
  679. mov Temp2, A
  680. ELSEIF PWM_BITS_H == 2 ; 10-bit pwm
  681. clr C
  682. mov A, Temp5
  683. rrc A
  684. cpl A
  685. anl A, #3
  686. mov Temp3, A
  687. mov A, Temp4
  688. rrc A
  689. cpl A
  690. mov Temp2, A
  691. ELSEIF PWM_BITS_H == 1 ; 9-bit pwm
  692. mov B, Temp5
  693. mov A, Temp4
  694. mov C, B.0
  695. rrc A
  696. mov C, B.1
  697. rrc A
  698. cpl A
  699. mov Temp2, A
  700. mov A, Temp5
  701. rr A
  702. rr A
  703. cpl A
  704. anl A, #1
  705. mov Temp3, A
  706. ELSEIF PWM_BITS_H == 0 ; 8-bit pwm
  707. mov A, Temp2 ; Temp2 already 8-bit
  708. cpl A
  709. mov Temp2, A
  710. mov Temp3, #0
  711. ENDIF
  712. ; 10-bit effective dithering of 8/9-bit pwm
  713. IF PWM_BITS_H < 2
  714. mov A, Temp4 ; 11-bit low byte
  715. cpl A
  716. rr A
  717. anl A, #((1 SHL (2-PWM_BITS_H))-1); Get index into dithering pattern table
  718. add A, #Dithering_Patterns
  719. mov Temp1, A ; Reuse DShot pwm pointer since it is not currently in use.
  720. mov A, @Temp1 ; Retrieve pattern
  721. rl A ; Rotate pattern
  722. mov @Temp1, A ; Store pattern
  723. jnb ACC.0, dithering_done
  724. mov A, Temp2
  725. add A, #1
  726. mov Temp2, A
  727. IF PWM_BITS_H != 0
  728. mov A, Temp3
  729. addc A, #0
  730. mov Temp3, A
  731. jnb ACC.PWM_BITS_H, dithering_done
  732. dec Temp2
  733. dec Temp3
  734. ELSE
  735. jnz dithering_done
  736. dec Temp2
  737. ENDIF
  738. dithering_done:
  739. ENDIF
  740. ; Set pwm registers
  741. IF FETON_DELAY != 0
  742. clr C
  743. mov A, Temp2 ; Skew damping fet timing
  744. IF MCU_48MHZ == 0
  745. subb A, #((FETON_DELAY+1) SHR 1)
  746. ELSE
  747. subb A, #(FETON_DELAY)
  748. ENDIF
  749. mov Temp4, A
  750. mov A, Temp3
  751. subb A, #0
  752. mov Temp5, A
  753. jnc t1_int_set_pwm_damp_set
  754. clr A
  755. mov Temp4, A
  756. mov Temp5, A
  757. t1_int_set_pwm_damp_set:
  758. ENDIF
  759. mov Power_Pwm_Reg_L, Temp2
  760. mov Power_Pwm_Reg_H, Temp3
  761. IF FETON_DELAY != 0
  762. mov Damp_Pwm_Reg_L, Temp4
  763. mov Damp_Pwm_Reg_H, Temp5
  764. ENDIF
  765. mov Rcp_Timeout_Cntd, #10 ; Set timeout count
  766. ; Prepare DShot telemetry
  767. jnb Flag_RCP_DSHOT_INVERTED, t1_int_exit_no_tlm ; Only send telemetry for inverted DShot
  768. jnb Flag_PACKET_PENDING, t1_int_exit_no_tlm ; Check if telemetry packet is ready
  769. ; Prepare timer 0 for sending telemetry data
  770. ; todo: dshot150
  771. ;mov Temp2, CKCON0 ; Save value to restore later
  772. mov CKCON0, #01h ; Timer 0 is system clock divided by 4
  773. mov TMOD, #0A2h ; Timer 0 runs free not gated by INT0
  774. mov TL0, DShot_GCR_Start_Delay ; Telemetry will begin after this delay
  775. clr TCON_TF0 ; Clear timer 0 overflow flag
  776. setb IE_ET0 ; Enable timer 0 interrupts
  777. ; Configure RTX_PIN for digital output
  778. setb RTX_PORT.RTX_PIN ; Default to high level
  779. orl RTX_MDOUT, #(1 SHL RTX_PIN) ; Set output mode to push-pull
  780. mov Temp1, #0 ; Set pointer to start
  781. sjmp t1_int_exit_no_int
  782. t1_int_exit_no_tlm:
  783. mov Temp1, #0 ; Set pointer to start
  784. mov TL0, #0 ; Reset timer 0
  785. setb IE_EX0 ; Enable int0 interrupts
  786. setb IE_EX1 ; Enable int1 interrupts
  787. Enable_PCA_Interrupt ; Enable pca interrupts
  788. t1_int_exit_no_int:
  789. pop B ; Restore preserved registers
  790. pop ACC
  791. pop PSW
  792. reti
  793. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  794. ;
  795. ; Timer 2 interrupt routine
  796. ;
  797. ; Requirements: Temp variables can NOT be used since PSW.x is not set
  798. ;
  799. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  800. t2_int: ; Happens every 32ms
  801. push ACC
  802. clr TMR2CN0_TF2H ; Clear interrupt flag
  803. inc Timer2_X
  804. IF MCU_48MHZ == 1
  805. jnb Flag_CLOCK_SET_AT_48MHZ, t2_int_start
  806. ; Check skip variable
  807. jbc Flag_SKIP_T2_INT, t2_int_exit ; Skip this interrupt
  808. t2_int_start:
  809. setb Flag_SKIP_T2_INT ; Skip next interrupt
  810. ENDIF
  811. ; Update RC pulse timeout counter
  812. mov A, Rcp_Timeout_Cntd ; RC pulse timeout count zero?
  813. jz ($+4) ; Yes - do not decrement
  814. dec Rcp_Timeout_Cntd ; No decrement
  815. jnb Flag_RCP_STOP, t2_int_exit ; Exit if pulse is above stop value
  816. inc Rcp_Stop_Cnt ; Otherwise, increment stop counter
  817. mov A, Rcp_Stop_Cnt
  818. jnz ($+4) ; Branch if counter has not wrapped
  819. dec Rcp_Stop_Cnt ; Set stop counter to max
  820. t2_int_exit:
  821. pop ACC ; Restore preserved registers
  822. reti
  823. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  824. ;
  825. ; Timer 3 interrupt routine
  826. ;
  827. ; Requirements: Temp variables can NOT be used since PSW.x is not set
  828. ; ACC can not be used, as it is not pushed to stack
  829. ;
  830. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  831. t3_int: ; Used for commutation timing
  832. clr IE_EA ; Disable all interrupts
  833. anl EIE1, #7Fh ; Disable timer 3 interrupts
  834. anl TMR3CN0, #07Fh ; Clear timer 3 interrupt flag
  835. mov TMR3RLL, #0FAh ; Set a short delay before next interrupt
  836. mov TMR3RLH, #0FFh
  837. clr Flag_T3_PENDING ; Flag that timer has wrapped
  838. setb IE_EA ; Enable all interrupts
  839. reti
  840. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  841. ;
  842. ; Int0 interrupt routine
  843. ;
  844. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  845. int0_int: ; Used for RC pulse timing
  846. push ACC
  847. mov A, TL0 ; Read pwm for DShot immediately
  848. mov TL1, DShot_Timer_Preset ; Reset sync timer
  849. ; Temp1 in register bank 1 points to pwm timings
  850. push PSW
  851. mov PSW, #8h
  852. movx @Temp1, A ; Store pwm
  853. inc Temp1
  854. pop PSW
  855. pop ACC
  856. reti
  857. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  858. ;
  859. ; Int1 interrupt routine
  860. ;
  861. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  862. int1_int: ; Used for RC pulse timing
  863. clr IE_EX1 ; Disable int1 interrupts
  864. setb TCON_TR1 ; Start timer 1
  865. clr TMR2CN0_TR2 ; Timer 2 disabled
  866. mov DShot_Frame_Start_L, TMR2L ; Read timer value
  867. mov DShot_Frame_Start_H, TMR2H
  868. setb TMR2CN0_TR2 ; Timer 2 enabled
  869. reti
  870. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  871. ;
  872. ; PCA interrupt routine
  873. ;
  874. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  875. pca_int: ; Used for setting pwm registers
  876. clr IE_EA
  877. push ACC
  878. IF FETON_DELAY != 0 ; HI/LO enable style drivers
  879. mov A, PCA0L ; Read low byte first, to transfer high byte to holding register
  880. mov A, PCA0H
  881. jnb Flag_LOW_PWM_POWER, pca_int_hi_pwm
  882. ; Power below 50%, update pca in the 0x00-0x0F range
  883. jb ACC.PWM_BITS_H, pca_int_exit ; PWM edge selection bit (continue if up edge)
  884. sjmp pca_int_set_pwm
  885. pca_int_hi_pwm:
  886. ; Power above 50%, update pca in the 0x20-0x2F range
  887. jnb ACC.PWM_BITS_H, pca_int_exit ; PWM edge selection bit (continue if down edge)
  888. pca_int_set_pwm:
  889. IF PWM_BITS_H != 0
  890. jb ACC.(PWM_BITS_H-1), pca_int_exit
  891. ELSE
  892. mov A, PCA0L
  893. jb ACC.7, pca_int_exit
  894. ENDIF
  895. ENDIF
  896. ; Set power pwm auto-reload registers
  897. IF PWM_BITS_H != 0
  898. mov PCA0_POWER_L, Power_Pwm_Reg_L
  899. mov PCA0_POWER_H, Power_Pwm_Reg_H
  900. ELSE
  901. mov PCA0_POWER_H, Power_Pwm_Reg_L
  902. ENDIF
  903. IF FETON_DELAY != 0
  904. ; Set damp pwm auto-reload registers
  905. IF PWM_BITS_H != 0
  906. mov PCA0_DAMP_L, Damp_Pwm_Reg_L
  907. mov PCA0_DAMP_H, Damp_Pwm_Reg_H
  908. ELSE
  909. mov PCA0_DAMP_H, Damp_Pwm_Reg_L
  910. ENDIF
  911. ENDIF
  912. setb Flag_LOW_PWM_POWER
  913. IF PWM_BITS_H != 0
  914. mov A, Power_Pwm_Reg_H
  915. jb ACC.(PWM_BITS_H-1), ($+5)
  916. ELSE
  917. mov A, Power_Pwm_Reg_L
  918. jb ACC.7, ($+5)
  919. ENDIF
  920. clr Flag_LOW_PWM_POWER
  921. Disable_COVF_Interrupt
  922. IF FETON_DELAY == 0 ; EN/PWM style drivers
  923. Disable_CCF_Interrupt
  924. ENDIF
  925. anl EIE1, #0EFh ; Pwm updated, disable pca interrupts
  926. pca_int_exit:
  927. Clear_COVF_Interrupt
  928. IF FETON_DELAY == 0
  929. Clear_CCF_Interrupt
  930. ENDIF
  931. pop ACC ; Restore preserved registers
  932. setb IE_EA
  933. reti
  934. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  935. ;
  936. ; DShot GCR encode
  937. ;
  938. ; GCR encode e-period data for DShot telemetry
  939. ;
  940. ; Input
  941. ; - Temp1: Data pointer for storing pulse timings
  942. ; - A: 4-bit value to GCR encode
  943. ; - B: Time that must be added to transition
  944. ; Output
  945. ; - B: Time remaining to be added to next transition
  946. ;
  947. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  948. dshot_gcr_encode:
  949. anl A, #0Fh
  950. rl A ; Multiply by 2 to match jump offsets
  951. mov DPTR, #dshot_gcr_encode_jump_table
  952. jmp @A+DPTR
  953. dshot_gcr_encode_jump_table:
  954. ajmp dshot_gcr_encode_0_11001
  955. ajmp dshot_gcr_encode_1_11011
  956. ajmp dshot_gcr_encode_2_10010
  957. ajmp dshot_gcr_encode_3_10011
  958. ajmp dshot_gcr_encode_4_11101
  959. ajmp dshot_gcr_encode_5_10101
  960. ajmp dshot_gcr_encode_6_10110
  961. ajmp dshot_gcr_encode_7_10111
  962. ajmp dshot_gcr_encode_8_11010
  963. ajmp dshot_gcr_encode_9_01001
  964. ajmp dshot_gcr_encode_A_01010
  965. ajmp dshot_gcr_encode_B_01011
  966. ajmp dshot_gcr_encode_C_11110
  967. ajmp dshot_gcr_encode_D_01101
  968. ajmp dshot_gcr_encode_E_01110
  969. ajmp dshot_gcr_encode_F_01111
  970. ; GCR encoding is ordered by least significant bit first,
  971. ; and represented as pulse durations.
  972. dshot_gcr_encode_0_11001:
  973. Push_Mem Temp1, Tmp_B
  974. Push_Mem Temp1, DShot_GCR_Pulse_Time_3
  975. Push_Mem Temp1, DShot_GCR_Pulse_Time_1
  976. mov Tmp_B, DShot_GCR_Pulse_Time_1
  977. ret
  978. dshot_gcr_encode_1_11011:
  979. Push_Mem Temp1, Tmp_B
  980. Push_Mem Temp1, DShot_GCR_Pulse_Time_1
  981. Push_Mem Temp1, DShot_GCR_Pulse_Time_2
  982. Push_Mem Temp1, DShot_GCR_Pulse_Time_1
  983. mov Tmp_B, DShot_GCR_Pulse_Time_1
  984. ret
  985. dshot_gcr_encode_2_10010:
  986. DShot_GCR_Get_Time
  987. Push_Mem Temp1, A
  988. Push_Mem Temp1, DShot_GCR_Pulse_Time_3
  989. mov Tmp_B, DShot_GCR_Pulse_Time_1
  990. ret
  991. dshot_gcr_encode_3_10011:
  992. Push_Mem Temp1, Tmp_B
  993. Push_Mem Temp1, DShot_GCR_Pulse_Time_1
  994. Push_Mem Temp1, DShot_GCR_Pulse_Time_3
  995. mov Tmp_B, DShot_GCR_Pulse_Time_1
  996. ret
  997. dshot_gcr_encode_4_11101:
  998. Push_Mem Temp1, Tmp_B
  999. Push_Mem Temp1, DShot_GCR_Pulse_Time_2
  1000. Push_Mem Temp1, DShot_GCR_Pulse_Time_1
  1001. Push_Mem Temp1, DShot_GCR_Pulse_Time_1
  1002. mov Tmp_B, DShot_GCR_Pulse_Time_1
  1003. ret
  1004. dshot_gcr_encode_5_10101:
  1005. Push_Mem Temp1, Tmp_B
  1006. Push_Mem Temp1, DShot_GCR_Pulse_Time_2
  1007. Push_Mem Temp1, DShot_GCR_Pulse_Time_2
  1008. mov Tmp_B, DShot_GCR_Pulse_Time_1
  1009. ret
  1010. dshot_gcr_encode_6_10110:
  1011. DShot_GCR_Get_Time
  1012. Push_Mem Temp1, A
  1013. Push_Mem Temp1, DShot_GCR_Pulse_Time_1
  1014. Push_Mem Temp1, DShot_GCR_Pulse_Time_2
  1015. mov Tmp_B, DShot_GCR_Pulse_Time_1
  1016. ret
  1017. dshot_gcr_encode_7_10111:
  1018. Push_Mem Temp1, Tmp_B
  1019. Push_Mem Temp1, DShot_GCR_Pulse_Time_1
  1020. Push_Mem Temp1, DShot_GCR_Pulse_Time_1
  1021. Push_Mem Temp1, DShot_GCR_Pulse_Time_2
  1022. mov Tmp_B, DShot_GCR_Pulse_Time_1
  1023. ret
  1024. dshot_gcr_encode_8_11010:
  1025. DShot_GCR_Get_Time
  1026. Push_Mem Temp1, A
  1027. Push_Mem Temp1, DShot_GCR_Pulse_Time_2
  1028. Push_Mem Temp1, DShot_GCR_Pulse_Time_1
  1029. mov Tmp_B, DShot_GCR_Pulse_Time_1
  1030. ret
  1031. dshot_gcr_encode_9_01001:
  1032. Push_Mem Temp1, Tmp_B
  1033. Push_Mem Temp1, DShot_GCR_Pulse_Time_3
  1034. mov Tmp_B, DShot_GCR_Pulse_Time_2
  1035. ret
  1036. dshot_gcr_encode_A_01010:
  1037. DShot_GCR_Get_Time
  1038. Push_Mem Temp1, A
  1039. Push_Mem Temp1, DShot_GCR_Pulse_Time_2
  1040. mov Tmp_B, DShot_GCR_Pulse_Time_2
  1041. ret
  1042. dshot_gcr_encode_B_01011:
  1043. Push_Mem Temp1, Tmp_B
  1044. Push_Mem Temp1, DShot_GCR_Pulse_Time_1
  1045. Push_Mem Temp1, DShot_GCR_Pulse_Time_2
  1046. mov Tmp_B, DShot_GCR_Pulse_Time_2
  1047. ret
  1048. dshot_gcr_encode_C_11110:
  1049. DShot_GCR_Get_Time
  1050. Push_Mem Temp1, A
  1051. Push_Mem Temp1, DShot_GCR_Pulse_Time_1
  1052. Push_Mem Temp1, DShot_GCR_Pulse_Time_1
  1053. Push_Mem Temp1, DShot_GCR_Pulse_Time_1
  1054. mov Tmp_B, DShot_GCR_Pulse_Time_1
  1055. ret
  1056. dshot_gcr_encode_D_01101:
  1057. Push_Mem Temp1, Tmp_B
  1058. Push_Mem Temp1, DShot_GCR_Pulse_Time_2
  1059. Push_Mem Temp1, DShot_GCR_Pulse_Time_1
  1060. mov Tmp_B, DShot_GCR_Pulse_Time_2
  1061. ret
  1062. dshot_gcr_encode_E_01110:
  1063. DShot_GCR_Get_Time
  1064. Push_Mem Temp1, A
  1065. Push_Mem Temp1, DShot_GCR_Pulse_Time_1
  1066. Push_Mem Temp1, DShot_GCR_Pulse_Time_1
  1067. mov Tmp_B, DShot_GCR_Pulse_Time_2
  1068. ret
  1069. dshot_gcr_encode_F_01111:
  1070. Push_Mem Temp1, Tmp_B
  1071. Push_Mem Temp1, DShot_GCR_Pulse_Time_1
  1072. Push_Mem Temp1, DShot_GCR_Pulse_Time_1
  1073. Push_Mem Temp1, DShot_GCR_Pulse_Time_1
  1074. mov Tmp_B, DShot_GCR_Pulse_Time_2
  1075. ret
  1076. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  1077. ;
  1078. ; DShot 12-bit encode
  1079. ;
  1080. ; Encodes 16-bit e-period as a 12-bit value of the form:
  1081. ; <e e e m m m m m m m m m> where M SHL E ~ e-period [us]
  1082. ;
  1083. ; Note: Not callable to improve performance
  1084. ;
  1085. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  1086. dshot_12bit_7:
  1087. ;mov A, Tlm_Data_H
  1088. mov C, Tlm_Data_L.7
  1089. rlc A
  1090. mov Tlm_Data_L, A
  1091. mov Tlm_Data_H, #0fh
  1092. ajmp dshot_tlm_12bit_encoded
  1093. dshot_12bit_6:
  1094. ;mov A, Tlm_Data_H
  1095. mov C, Tlm_Data_L.7
  1096. rlc A
  1097. mov C, Tlm_Data_L.6
  1098. rlc A
  1099. mov Tlm_Data_L, A
  1100. mov Tlm_Data_H, #0dh
  1101. ajmp dshot_tlm_12bit_encoded
  1102. dshot_12bit_5:
  1103. ;mov A, Tlm_Data_H
  1104. mov C, Tlm_Data_L.7
  1105. rlc A
  1106. mov C, Tlm_Data_L.6
  1107. rlc A
  1108. mov C, Tlm_Data_L.5
  1109. rlc A
  1110. mov Tlm_Data_L, A
  1111. mov Tlm_Data_H, #0bh
  1112. ajmp dshot_tlm_12bit_encoded
  1113. dshot_12bit_4:
  1114. mov A, Tlm_Data_L
  1115. anl A, #0f0h
  1116. clr Tlm_Data_H.4
  1117. orl A, Tlm_Data_H
  1118. swap A
  1119. mov Tlm_Data_L, A
  1120. mov Tlm_Data_H, #09h
  1121. ajmp dshot_tlm_12bit_encoded
  1122. dshot_12bit_3:
  1123. mov A, Tlm_Data_L
  1124. mov C, Tlm_Data_H.0
  1125. rrc A
  1126. mov C, Tlm_Data_H.1
  1127. rrc A
  1128. mov C, Tlm_Data_H.2
  1129. rrc A
  1130. mov Tlm_Data_L, A
  1131. mov Tlm_Data_H, #07h
  1132. ajmp dshot_tlm_12bit_encoded
  1133. dshot_12bit_2:
  1134. mov A, Tlm_Data_L
  1135. mov C, Tlm_Data_H.0
  1136. rrc A
  1137. mov C, Tlm_Data_H.1
  1138. rrc A
  1139. mov Tlm_Data_L, A
  1140. mov Tlm_Data_H, #05h
  1141. ajmp dshot_tlm_12bit_encoded
  1142. dshot_12bit_1:
  1143. mov A, Tlm_Data_L
  1144. mov C, Tlm_Data_H.0
  1145. rrc A
  1146. mov Tlm_Data_L, A
  1147. mov Tlm_Data_H, #03h
  1148. ajmp dshot_tlm_12bit_encoded
  1149. dshot_12bit_encode:
  1150. ; Encode 16-bit e-period as a 12-bit value
  1151. jb ACC.7, dshot_12bit_7 ; ACC = Tlm_Data_H
  1152. jb ACC.6, dshot_12bit_6
  1153. jb ACC.5, dshot_12bit_5
  1154. jb ACC.4, dshot_12bit_4
  1155. jb ACC.3, dshot_12bit_3
  1156. jb ACC.2, dshot_12bit_2
  1157. jb ACC.1, dshot_12bit_1
  1158. mov A, Tlm_Data_L ; Already 12-bit (E=0)
  1159. ajmp dshot_tlm_12bit_encoded
  1160. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  1161. ;
  1162. ; DShot telemetry create packet
  1163. ;
  1164. ; Create DShot telemetry packet and prepare it for being sent
  1165. ; The routine is divided into 6 sections that can return early
  1166. ; in order to reduce commutation interference
  1167. ;
  1168. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  1169. dshot_tlm_create_packet:
  1170. push PSW
  1171. mov PSW, #10h ; Select register bank 2
  1172. Early_Return_Packet_Stage 0
  1173. ; Read commutation period
  1174. clr IE_EA
  1175. mov Tlm_Data_L, Comm_Period4x_L
  1176. mov Tlm_Data_H, Comm_Period4x_H
  1177. setb IE_EA
  1178. ; Multiply period by 3/4 (1/2 + 1/4)
  1179. mov A, Tlm_Data_L
  1180. mov C, Tlm_Data_H.0
  1181. rrc A
  1182. mov Temp2, A
  1183. mov C, Tlm_Data_H.1
  1184. rrc A
  1185. add A, Temp2
  1186. mov Tlm_Data_L, A
  1187. mov A, Tlm_Data_H
  1188. rr A
  1189. clr ACC.7
  1190. mov Temp2, A
  1191. rr A
  1192. clr ACC.7
  1193. addc A, Temp2
  1194. mov Tlm_Data_H, A
  1195. Early_Return_Packet_Stage 1
  1196. mov A, Tlm_Data_H
  1197. ; 12-bit encode telemetry data
  1198. jnz dshot_12bit_encode
  1199. mov A, Tlm_Data_L ; Already 12-bit
  1200. jnz dshot_tlm_12bit_encoded
  1201. ; If period is zero then reset to FFFFh (FFFh for 12-bit)
  1202. mov Tlm_Data_H, #0Fh
  1203. mov Tlm_Data_L, #0FFh
  1204. dshot_tlm_12bit_encoded:
  1205. Early_Return_Packet_Stage 2
  1206. mov A, Tlm_Data_L
  1207. ; Compute inverted xor checksum (4-bit)
  1208. swap A
  1209. xrl A, Tlm_Data_L
  1210. xrl A, Tlm_Data_H
  1211. cpl A
  1212. ; GCR encode the telemetry data (16-bit)
  1213. mov Temp1, #Temp_Storage ; Store pulse timings in Temp_Storage
  1214. mov Tmp_B, DShot_GCR_Pulse_Time_1 ; Final transition time
  1215. call dshot_gcr_encode ; GCR encode lowest 4-bit of A (store through Temp1)
  1216. Early_Return_Packet_Stage 3
  1217. mov A, Tlm_Data_L
  1218. call dshot_gcr_encode
  1219. Early_Return_Packet_Stage 4
  1220. mov A, Tlm_Data_L
  1221. swap A
  1222. call dshot_gcr_encode
  1223. Early_Return_Packet_Stage 5
  1224. mov A, Tlm_Data_H
  1225. call dshot_gcr_encode
  1226. Push_Mem Temp1, Tmp_B ; Initial transition time
  1227. mov Temp5, #0
  1228. setb Flag_PACKET_PENDING
  1229. pop PSW
  1230. ret
  1231. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  1232. ;
  1233. ; Wait a number of milliseconds (Multiple entry points)
  1234. ;
  1235. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  1236. wait1ms:
  1237. mov Temp2, #1
  1238. sjmp waitxms_o
  1239. wait10ms:
  1240. mov Temp2, #10
  1241. sjmp waitxms_o
  1242. wait100ms:
  1243. mov Temp2, #100
  1244. sjmp waitxms_o
  1245. wait200ms:
  1246. mov Temp2, #200
  1247. sjmp waitxms_o
  1248. waitxms_o: ; Outer loop
  1249. mov Temp1, #23
  1250. waitxms_m: ; Middle loop
  1251. clr A
  1252. djnz ACC, $ ; Inner loop (41.8us - 1024 cycles)
  1253. djnz Temp1, waitxms_m
  1254. djnz Temp2, waitxms_o
  1255. ret
  1256. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  1257. ;
  1258. ; Set pwm limit low rpm
  1259. ;
  1260. ; Sets power limit for low rpms and disables demag for low rpms
  1261. ;
  1262. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  1263. set_pwm_limit:
  1264. jb Flag_HIGH_RPM, set_pwm_limit_high_rpm ; If high rpm, limit pwm by rpm instead
  1265. ;set_pwm_limit_low_rpm:
  1266. ; Set pwm limit
  1267. mov Temp1, #0FFh ; Default full power
  1268. jb Flag_STARTUP_PHASE, set_pwm_limit_low_rpm_exit ; Exit if startup phase set
  1269. mov Temp2, #Pgm_Enable_Power_Prot ; Check if low RPM power protection is enabled
  1270. mov A, @Temp2
  1271. jz set_pwm_limit_low_rpm_exit ; Exit if disabled
  1272. mov A, Comm_Period4x_H
  1273. jz set_pwm_limit_low_rpm_exit ; Avoid divide by zero
  1274. mov A, #255 ; Divide 255 by Comm_Period4x_H
  1275. mov B, Comm_Period4x_H
  1276. div AB
  1277. mov B, Low_Rpm_Pwr_Slope ; Multiply by slope
  1278. jnb Flag_INITIAL_RUN_PHASE, ($+6) ; More protection for initial run phase
  1279. mov B, #5
  1280. mul AB
  1281. mov Temp1, A ; Set new limit
  1282. xch A, B
  1283. jz ($+4) ; Limit to max
  1284. mov Temp1, #0FFh
  1285. clr C
  1286. mov A, Temp1 ; Limit to min
  1287. subb A, Pwm_Limit_Beg
  1288. jnc set_pwm_limit_low_rpm_exit
  1289. mov Temp1, Pwm_Limit_Beg
  1290. set_pwm_limit_low_rpm_exit:
  1291. mov Pwm_Limit_By_Rpm, Temp1
  1292. ret
  1293. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  1294. ;
  1295. ; Set pwm limit high rpm
  1296. ;
  1297. ; Sets power limit for high rpms
  1298. ;
  1299. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  1300. set_pwm_limit_high_rpm:
  1301. clr C
  1302. mov A, Comm_Period4x_L
  1303. IF MCU_48MHZ == 1
  1304. subb A, #0A0h ; Limit Comm_Period to 160, which is 500k erpm
  1305. ELSE
  1306. subb A, #0E4h ; Limit Comm_Period to 228, which is 350k erpm
  1307. ENDIF
  1308. mov A, Comm_Period4x_H
  1309. subb A, #00h
  1310. mov A, Pwm_Limit_By_Rpm
  1311. jnc set_pwm_limit_high_rpm_inc_limit
  1312. dec A
  1313. sjmp set_pwm_limit_high_rpm_store
  1314. set_pwm_limit_high_rpm_inc_limit:
  1315. inc A
  1316. set_pwm_limit_high_rpm_store:
  1317. jz ($+4)
  1318. mov Pwm_Limit_By_Rpm, A
  1319. ret
  1320. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  1321. ;
  1322. ; Check temperature, power supply voltage and limit power
  1323. ;
  1324. ; Used to limit main motor power in order to maintain the required voltage
  1325. ;
  1326. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  1327. check_temp_voltage_and_limit_power:
  1328. inc Adc_Conversion_Cnt ; Increment conversion counter
  1329. clr C
  1330. mov A, Adc_Conversion_Cnt ; Is conversion count equal to temp rate?
  1331. subb A, #8
  1332. jc check_voltage_start ; No - check voltage
  1333. ; Wait for ADC conversion to complete
  1334. jnb ADC0CN0_ADINT, check_temp_voltage_and_limit_power
  1335. ; Read ADC result
  1336. Read_Adc_Result
  1337. ; Stop ADC
  1338. Stop_Adc
  1339. mov Adc_Conversion_Cnt, #0 ; Yes - temperature check. Reset counter
  1340. mov A, Temp2 ; Move ADC MSB to Temp3
  1341. mov Temp3, A
  1342. mov Temp2, #Pgm_Enable_Temp_Prot ; Is temp protection enabled?
  1343. mov A, @Temp2
  1344. jz temp_check_exit ; No - branch
  1345. mov A, Temp3 ; Is temperature reading below 256?
  1346. jnz temp_average_inc_dec ; No - proceed
  1347. mov A, Current_Average_Temp ; Yes - decrement average
  1348. jz temp_average_updated ; Already zero - no change
  1349. sjmp temp_average_dec ; Decrement
  1350. temp_average_inc_dec:
  1351. clr C
  1352. mov A, Temp1 ; Check if current temperature is above or below average
  1353. subb A, Current_Average_Temp
  1354. jz temp_average_updated_load_acc ; Equal - no change
  1355. mov A, Current_Average_Temp ; Above - increment average
  1356. jnc temp_average_inc
  1357. jz temp_average_updated ; Below - decrement average if average is not already zero
  1358. temp_average_dec:
  1359. dec A ; Decrement average
  1360. sjmp temp_average_updated
  1361. temp_average_inc:
  1362. inc A ; Increment average
  1363. jz temp_average_dec
  1364. sjmp temp_average_updated
  1365. temp_average_updated_load_acc:
  1366. mov A, Current_Average_Temp
  1367. temp_average_updated:
  1368. mov Current_Average_Temp, A
  1369. clr C
  1370. subb A, Temp_Prot_Limit ; Is temperature below first limit?
  1371. jc temp_check_exit ; Yes - exit
  1372. mov Pwm_Limit, #192 ; No - limit pwm
  1373. clr C
  1374. subb A, #(TEMP_LIMIT_STEP/2) ; Is temperature below second limit
  1375. jc temp_check_exit ; Yes - exit
  1376. mov Pwm_Limit, #128 ; No - limit pwm
  1377. clr C
  1378. subb A, #(TEMP_LIMIT_STEP/2) ; Is temperature below third limit
  1379. jc temp_check_exit ; Yes - exit
  1380. mov Pwm_Limit, #64 ; No - limit pwm
  1381. clr C
  1382. subb A, #(TEMP_LIMIT_STEP/2) ; Is temperature below final limit
  1383. jc temp_check_exit ; Yes - exit
  1384. mov Pwm_Limit, #0 ; No - limit pwm
  1385. temp_check_exit:
  1386. ret
  1387. check_voltage_start:
  1388. ; Increase pwm limit
  1389. mov A, Pwm_Limit
  1390. add A, #16
  1391. jnc ($+4) ; If not max - branch
  1392. mov A, #255
  1393. mov Pwm_Limit, A ; Increment limit
  1394. ret
  1395. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  1396. ;
  1397. ; Initialize timing routine
  1398. ;
  1399. ; Part of initialization before motor start
  1400. ;
  1401. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  1402. initialize_timing:
  1403. mov Comm_Period4x_L, #00h ; Set commutation period registers
  1404. mov Comm_Period4x_H, #0F0h
  1405. ret
  1406. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  1407. ;
  1408. ; Calculate next commutation timing routine
  1409. ;
  1410. ; Called immediately after each commutation
  1411. ; Also sets up timer 3 to wait advance timing
  1412. ; Two entry points are used
  1413. ;
  1414. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  1415. calc_next_comm_timing: ; Entry point for run phase
  1416. ; Read commutation time
  1417. clr IE_EA
  1418. clr TMR2CN0_TR2 ; Timer 2 disabled
  1419. mov Temp1, TMR2L ; Load timer value
  1420. mov Temp2, TMR2H
  1421. mov Temp3, Timer2_X
  1422. jnb TMR2CN0_TF2H, ($+4) ; Check if interrupt is pending
  1423. inc Temp3 ; If it is pending, then timer has already wrapped
  1424. setb TMR2CN0_TR2 ; Timer 2 enabled
  1425. setb IE_EA
  1426. IF MCU_48MHZ == 1
  1427. clr C
  1428. mov A, Temp3
  1429. rrc A
  1430. mov Temp3, A
  1431. mov A, Temp2
  1432. rrc A
  1433. mov Temp2, A
  1434. mov A, Temp1
  1435. rrc A
  1436. mov Temp1, A
  1437. ENDIF
  1438. ; Calculate this commutation time
  1439. mov Temp4, Prev_Comm_L
  1440. mov Temp5, Prev_Comm_H
  1441. mov Prev_Comm_L, Temp1 ; Store timestamp as previous commutation
  1442. mov Prev_Comm_H, Temp2
  1443. clr C
  1444. mov A, Temp1
  1445. subb A, Temp4 ; Calculate the new commutation time
  1446. mov Temp1, A
  1447. mov A, Temp2
  1448. subb A, Temp5
  1449. jb Flag_STARTUP_PHASE, calc_next_comm_startup
  1450. IF MCU_48MHZ == 1
  1451. anl A, #7Fh
  1452. ENDIF
  1453. mov Temp2, A
  1454. jnb Flag_HIGH_RPM, calc_next_comm_normal ; Branch normal rpm
  1455. ajmp calc_next_comm_timing_fast ; Branch high rpm
  1456. calc_next_comm_startup:
  1457. mov Temp6, Prev_Comm_X
  1458. mov Prev_Comm_X, Temp3 ; Store extended timestamp as previous commutation
  1459. mov Temp2, A
  1460. mov A, Temp3
  1461. subb A, Temp6 ; Calculate the new extended commutation time
  1462. IF MCU_48MHZ == 1
  1463. anl A, #7Fh
  1464. ENDIF
  1465. mov Temp3, A
  1466. jz calc_next_comm_startup_no_X
  1467. mov Temp1, #0FFh
  1468. mov Temp2, #0FFh
  1469. sjmp calc_next_comm_startup_average
  1470. calc_next_comm_startup_no_X:
  1471. mov Temp7, Prev_Prev_Comm_L
  1472. mov Temp8, Prev_Prev_Comm_H
  1473. mov Prev_Prev_Comm_L, Temp4
  1474. mov Prev_Prev_Comm_H, Temp5
  1475. mov Temp1, Prev_Comm_L ; Reload this commutation time
  1476. mov Temp2, Prev_Comm_H
  1477. clr C
  1478. mov A, Temp1
  1479. subb A, Temp7 ; Calculate the new commutation time based upon the two last commutations (to reduce sensitivity to offset)
  1480. mov Temp1, A
  1481. mov A, Temp2
  1482. subb A, Temp8
  1483. mov Temp2, A
  1484. calc_next_comm_startup_average:
  1485. clr C
  1486. mov A, Comm_Period4x_H ; Average with previous and save
  1487. rrc A
  1488. mov Temp4, A
  1489. mov A, Comm_Period4x_L
  1490. rrc A
  1491. mov Temp3, A
  1492. mov A, Temp1
  1493. add A, Temp3
  1494. mov Comm_Period4x_L, A
  1495. mov A, Temp2
  1496. addc A, Temp4
  1497. mov Comm_Period4x_H, A
  1498. jnc ($+8)
  1499. mov Comm_Period4x_L, #0FFh
  1500. mov Comm_Period4x_H, #0FFh
  1501. sjmp calc_new_wait_times_setup
  1502. calc_next_comm_normal:
  1503. ; Calculate new commutation time
  1504. mov Temp3, Comm_Period4x_L ; Comm_Period4x(-l-h) holds the time of 4 commutations
  1505. mov Temp4, Comm_Period4x_H
  1506. mov Temp5, Comm_Period4x_L ; Copy variables
  1507. mov Temp6, Comm_Period4x_H
  1508. mov Temp7, #4 ; Divide Comm_Period4x 4 times as default
  1509. mov Temp8, #2 ; Divide new commutation time 2 times as default
  1510. clr C
  1511. mov A, Temp4
  1512. subb A, #04h
  1513. jc calc_next_comm_avg_period_div
  1514. dec Temp7 ; Reduce averaging time constant for low speeds
  1515. dec Temp8
  1516. clr C
  1517. mov A, Temp4
  1518. subb A, #08h
  1519. jc calc_next_comm_avg_period_div
  1520. jb Flag_INITIAL_RUN_PHASE, calc_next_comm_avg_period_div ; Do not average very fast during initial run
  1521. dec Temp7 ; Reduce averaging time constant more for even lower speeds
  1522. dec Temp8
  1523. calc_next_comm_avg_period_div:
  1524. clr C
  1525. mov A, Temp6
  1526. rrc A ; Divide by 2
  1527. mov Temp6, A
  1528. mov A, Temp5
  1529. rrc A
  1530. mov Temp5, A
  1531. djnz Temp7, calc_next_comm_avg_period_div
  1532. clr C
  1533. mov A, Temp3
  1534. subb A, Temp5 ; Subtract a fraction
  1535. mov Temp3, A
  1536. mov A, Temp4
  1537. subb A, Temp6
  1538. mov Temp4, A
  1539. mov A, Temp8 ; Divide new time
  1540. jz calc_next_comm_new_period_div_done
  1541. calc_next_comm_new_period_div:
  1542. clr C
  1543. mov A, Temp2
  1544. rrc A ; Divide by 2
  1545. mov Temp2, A
  1546. mov A, Temp1
  1547. rrc A
  1548. mov Temp1, A
  1549. djnz Temp8, calc_next_comm_new_period_div
  1550. calc_next_comm_new_period_div_done:
  1551. mov A, Temp3
  1552. add A, Temp1 ; Add the divided new time
  1553. mov Temp3, A
  1554. mov A, Temp4
  1555. addc A, Temp2
  1556. mov Temp4, A
  1557. mov Comm_Period4x_L, Temp3 ; Store Comm_Period4x_X
  1558. mov Comm_Period4x_H, Temp4
  1559. jnc calc_new_wait_times_setup; If period larger than 0xffff - go to slow case
  1560. mov Temp4, #0FFh
  1561. mov Comm_Period4x_L, Temp4 ; Set commutation period registers to very slow timing (0xffff)
  1562. mov Comm_Period4x_H, Temp4
  1563. calc_new_wait_times_setup:
  1564. ; Set high rpm bit (if above 156k erpm)
  1565. clr C
  1566. mov A, Temp4
  1567. subb A, #2
  1568. jnc ($+4)
  1569. setb Flag_HIGH_RPM ; Set high rpm bit
  1570. ; Load programmed commutation timing
  1571. jnb Flag_STARTUP_PHASE, calc_new_wait_per_startup_done ; Set dedicated timing during startup
  1572. mov Temp8, #3
  1573. sjmp calc_new_wait_per_demag_done
  1574. calc_new_wait_per_startup_done:
  1575. mov Temp1, #Pgm_Comm_Timing ; Load timing setting
  1576. mov A, @Temp1
  1577. mov Temp8, A ; Store in Temp8
  1578. clr C
  1579. mov A, Demag_Detected_Metric ; Check demag metric
  1580. subb A, #130
  1581. jc calc_new_wait_per_demag_done
  1582. inc Temp8 ; Increase timing
  1583. clr C
  1584. mov A, Demag_Detected_Metric
  1585. subb A, #160
  1586. jc ($+3)
  1587. inc Temp8 ; Increase timing again
  1588. clr C
  1589. mov A, Temp8 ; Limit timing to max
  1590. subb A, #6
  1591. jc ($+4)
  1592. mov Temp8, #5 ; Set timing to max
  1593. calc_new_wait_per_demag_done:
  1594. ; Set timing reduction
  1595. mov Temp7, #2
  1596. ; Load current commutation timing
  1597. mov A, Comm_Period4x_H ; Divide 4 times
  1598. swap A
  1599. anl A, #00Fh
  1600. mov Temp2, A
  1601. mov A, Comm_Period4x_H
  1602. swap A
  1603. anl A, #0F0h
  1604. mov Temp1, A
  1605. mov A, Comm_Period4x_L
  1606. swap A
  1607. anl A, #00Fh
  1608. add A, Temp1
  1609. mov Temp1, A
  1610. clr C
  1611. mov A, Temp1
  1612. subb A, Temp7
  1613. mov Temp3, A
  1614. mov A, Temp2
  1615. subb A, #0
  1616. mov Temp4, A
  1617. jc load_min_time ; Check that result is still positive
  1618. jnz calc_new_wait_times_exit ; Check that result is still above minumum
  1619. mov A, Temp3
  1620. jnz calc_new_wait_times_exit
  1621. load_min_time:
  1622. mov Temp3, #1
  1623. mov Temp4, #0
  1624. calc_new_wait_times_exit:
  1625. sjmp wait_advance_timing
  1626. ; Fast calculation (Comm_Period4x_H less than 2)
  1627. calc_next_comm_timing_fast:
  1628. ; Calculate new commutation time
  1629. mov Temp3, Comm_Period4x_L ; Comm_Period4x(-l-h) holds the time of 4 commutations
  1630. mov Temp4, Comm_Period4x_H
  1631. mov A, Temp4 ; Divide by 2 4 times
  1632. swap A
  1633. mov Temp7, A
  1634. mov A, Temp3
  1635. swap A
  1636. anl A, #0Fh
  1637. orl A, Temp7
  1638. mov Temp5, A
  1639. clr C
  1640. mov A, Temp3 ; Subtract a fraction
  1641. subb A, Temp5
  1642. mov Temp3, A
  1643. mov A, Temp4
  1644. subb A, #0
  1645. mov Temp4, A
  1646. clr C
  1647. mov A, Temp1
  1648. rrc A ; Divide by 2 2 times
  1649. clr C
  1650. rrc A
  1651. mov Temp1, A
  1652. mov A, Temp3 ; Add the divided new time
  1653. add A, Temp1
  1654. mov Temp3, A
  1655. mov A, Temp4
  1656. addc A, #0
  1657. mov Temp4, A
  1658. mov Comm_Period4x_L, Temp3 ; Store Comm_Period4x_X
  1659. mov Comm_Period4x_H, Temp4
  1660. clr C
  1661. subb A, #2 ; If erpm below 156k - go to normal case
  1662. jc ($+4)
  1663. clr Flag_HIGH_RPM ; Clear high rpm bit
  1664. ; Set timing reduction
  1665. mov Temp1, #2
  1666. mov A, Temp4 ; Divide by 2 4 times
  1667. swap A
  1668. mov Temp7, A
  1669. mov Temp4, #0
  1670. mov A, Temp3
  1671. swap A
  1672. anl A, #0Fh
  1673. orl A, Temp7
  1674. mov Temp3, A
  1675. clr C
  1676. subb A, Temp1
  1677. mov Temp3, A
  1678. jc load_min_time_fast ; Check that result is still positive
  1679. jnz calc_new_wait_times_fast_done ; Check that result is still above minumum
  1680. load_min_time_fast:
  1681. mov Temp3, #1
  1682. calc_new_wait_times_fast_done:
  1683. mov Temp1, #Pgm_Comm_Timing ; Load timing setting
  1684. mov A, @Temp1
  1685. mov Temp8, A ; Store in Temp8
  1686. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  1687. ;
  1688. ; Wait advance timing routine
  1689. ; NOTE: Be VERY careful if using temp registers. They are passed over this routine
  1690. ;
  1691. ; Waits for the advance timing to elapse and sets up the next zero cross wait
  1692. ;
  1693. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  1694. wait_advance_timing:
  1695. Wait_For_Timer3
  1696. ; Setup next wait time
  1697. mov TMR3RLL, Wt_ZC_Tout_Start_L
  1698. mov TMR3RLH, Wt_ZC_Tout_Start_H
  1699. setb Flag_T3_PENDING
  1700. orl EIE1, #80h ; Enable timer 3 interrupts
  1701. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  1702. ;
  1703. ; Calculate new wait times routine
  1704. ;
  1705. ; Calculates new wait times
  1706. ;
  1707. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  1708. calc_new_wait_times:
  1709. clr C
  1710. clr A
  1711. subb A, Temp3 ; Negate
  1712. mov Temp1, A
  1713. clr A
  1714. subb A, Temp4
  1715. mov Temp2, A
  1716. IF MCU_48MHZ == 1
  1717. clr C
  1718. mov A, Temp1 ; Multiply by 2
  1719. rlc A
  1720. mov Temp1, A
  1721. mov A, Temp2
  1722. rlc A
  1723. mov Temp2, A
  1724. ENDIF
  1725. jb Flag_HIGH_RPM, calc_new_wait_times_fast ; Branch if high rpm
  1726. mov A, Temp1 ; Copy values
  1727. mov Temp3, A
  1728. mov A, Temp2
  1729. mov Temp4, A
  1730. setb C ; Negative numbers - set carry
  1731. mov A, Temp2
  1732. rrc A ; Divide by 2
  1733. mov Temp6, A
  1734. mov A, Temp1
  1735. rrc A
  1736. mov Temp5, A
  1737. mov Wt_Zc_Tout_Start_L, Temp1 ; Set 15deg time for zero cross scan timeout
  1738. mov Wt_Zc_Tout_Start_H, Temp2
  1739. clr C
  1740. mov A, Temp8 ; (Temp8 has Pgm_Comm_Timing)
  1741. subb A, #3 ; Is timing normal?
  1742. jz store_times_decrease ; Yes - branch
  1743. mov A, Temp8
  1744. jb ACC.0, adjust_timing_two_steps; If an odd number - branch
  1745. mov A, Temp1 ; Add 7.5deg and store in Temp1/2
  1746. add A, Temp5
  1747. mov Temp1, A
  1748. mov A, Temp2
  1749. addc A, Temp6
  1750. mov Temp2, A
  1751. mov A, Temp5 ; Store 7.5deg in Temp3/4
  1752. mov Temp3, A
  1753. mov A, Temp6
  1754. mov Temp4, A
  1755. sjmp store_times_up_or_down
  1756. adjust_timing_two_steps:
  1757. mov A, Temp1 ; Add 15deg and store in Temp1/2
  1758. setb C ; Add 1 to final result (Temp1/2 * 2 + 1)
  1759. addc A, Temp1
  1760. mov Temp1, A
  1761. mov A, Temp2
  1762. addc A, Temp2
  1763. mov Temp2, A
  1764. mov Temp3, #0FFh ; Store minimum time in Temp3/4
  1765. mov Temp4, #0FFh
  1766. store_times_up_or_down:
  1767. clr C
  1768. mov A, Temp8
  1769. subb A, #3 ; Is timing higher than normal?
  1770. jc store_times_decrease ; No - branch
  1771. store_times_increase:
  1772. mov Wt_Comm_Start_L, Temp3 ; Now commutation time (~60deg) divided by 4 (~15deg nominal)
  1773. mov Wt_Comm_Start_H, Temp4
  1774. mov Wt_Adv_Start_L, Temp1 ; New commutation advance time (~15deg nominal)
  1775. mov Wt_Adv_Start_H, Temp2
  1776. mov Wt_Zc_Scan_Start_L, Temp5 ; Use this value for zero cross scan delay (7.5deg)
  1777. mov Wt_Zc_Scan_Start_H, Temp6
  1778. sjmp wait_before_zc_scan
  1779. store_times_decrease:
  1780. mov Wt_Comm_Start_L, Temp1 ; Now commutation time (~60deg) divided by 4 (~15deg nominal)
  1781. mov Wt_Comm_Start_H, Temp2
  1782. mov Wt_Adv_Start_L, Temp3 ; New commutation advance time (~15deg nominal)
  1783. mov Wt_Adv_Start_H, Temp4
  1784. mov Wt_Zc_Scan_Start_L, Temp5 ; Use this value for zero cross scan delay (7.5deg)
  1785. mov Wt_Zc_Scan_Start_H, Temp6
  1786. jnb Flag_STARTUP_PHASE, store_times_exit
  1787. ; Set very short delays for all but advance time during startup, in order to widen zero cross capture range
  1788. mov Wt_Comm_Start_L, #0F0h
  1789. mov Wt_Comm_Start_H, #0FFh
  1790. mov Wt_Zc_Scan_Start_L, #0F0h
  1791. mov Wt_Zc_Scan_Start_H, #0FFh
  1792. mov Wt_Zc_Tout_Start_L, #0F0h
  1793. mov Wt_Zc_Tout_Start_H, #0FFh
  1794. store_times_exit:
  1795. sjmp wait_before_zc_scan
  1796. calc_new_wait_times_fast:
  1797. mov A, Temp1 ; Copy values
  1798. mov Temp3, A
  1799. setb C ; Negative numbers - set carry
  1800. rrc A ; Divide by 2
  1801. mov Temp5, A
  1802. mov Wt_Zc_Tout_Start_L, Temp1 ; Set 15deg time for zero cross scan timeout
  1803. clr C
  1804. mov A, Temp8 ; (Temp8 has Pgm_Comm_Timing)
  1805. subb A, #3 ; Is timing normal?
  1806. jz store_times_decrease_fast ; Yes - branch
  1807. mov A, Temp8
  1808. jb ACC.0, adjust_timing_two_steps_fast ; If an odd number - branch
  1809. mov A, Temp1 ; Add 7.5deg and store in Temp1
  1810. add A, Temp5
  1811. mov Temp1, A
  1812. mov A, Temp5 ; Store 7.5deg in Temp3
  1813. mov Temp3, A
  1814. sjmp store_times_up_or_down_fast
  1815. adjust_timing_two_steps_fast:
  1816. mov A, Temp1 ; Add 15deg and store in Temp1
  1817. add A, Temp1
  1818. add A, #1
  1819. mov Temp1, A
  1820. mov Temp3, #0FFh ; Store minimum time in Temp3
  1821. store_times_up_or_down_fast:
  1822. clr C
  1823. mov A, Temp8
  1824. subb A, #3 ; Is timing higher than normal?
  1825. jc store_times_decrease_fast ; No - branch
  1826. store_times_increase_fast:
  1827. mov Wt_Comm_Start_L, Temp3 ; Now commutation time (~60deg) divided by 4 (~15deg nominal)
  1828. mov Wt_Adv_Start_L, Temp1 ; New commutation advance time (~15deg nominal)
  1829. mov Wt_Zc_Scan_Start_L, Temp5 ; Use this value for zero cross scan delay (7.5deg)
  1830. sjmp wait_before_zc_scan
  1831. store_times_decrease_fast:
  1832. mov Wt_Comm_Start_L, Temp1 ; Now commutation time (~60deg) divided by 4 (~15deg nominal)
  1833. mov Wt_Adv_Start_L, Temp3 ; New commutation advance time (~15deg nominal)
  1834. mov Wt_Zc_Scan_Start_L, Temp5 ; Use this value for zero cross scan delay (7.5deg)
  1835. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  1836. ;
  1837. ; Wait before zero cross scan routine
  1838. ;
  1839. ; Waits for the zero cross scan wait time to elapse
  1840. ; Also sets up timer 3 for the zero cross scan timeout time
  1841. ;
  1842. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  1843. wait_before_zc_scan:
  1844. Wait_For_Timer3
  1845. mov Startup_Zc_Timeout_Cntd, #2
  1846. setup_zc_scan_timeout:
  1847. setb Flag_T3_PENDING
  1848. orl EIE1, #80h ; Enable timer 3 interrupts
  1849. mov A, Flags_Startup
  1850. jz wait_before_zc_scan_exit
  1851. mov Temp1, Comm_Period4x_L ; Set long timeout when starting
  1852. mov Temp2, Comm_Period4x_H
  1853. clr C
  1854. mov A, Temp2
  1855. rrc A
  1856. mov Temp2, A
  1857. mov A, Temp1
  1858. rrc A
  1859. mov Temp1, A
  1860. IF MCU_48MHZ == 0
  1861. clr C
  1862. mov A, Temp2
  1863. rrc A
  1864. mov Temp2, A
  1865. mov A, Temp1
  1866. rrc A
  1867. mov Temp1, A
  1868. ENDIF
  1869. jnb Flag_STARTUP_PHASE, setup_zc_scan_timeout_startup_done
  1870. mov A, Temp2
  1871. add A, #40h ; Increase timeout somewhat to avoid false wind up
  1872. mov Temp2, A
  1873. setup_zc_scan_timeout_startup_done:
  1874. clr IE_EA
  1875. anl EIE1, #7Fh ; Disable timer 3 interrupts
  1876. mov TMR3CN0, #00h ; Timer 3 disabled and interrupt flag cleared
  1877. clr C
  1878. clr A
  1879. subb A, Temp1 ; Set timeout
  1880. mov TMR3L, A
  1881. clr A
  1882. subb A, Temp2
  1883. mov TMR3H, A
  1884. mov TMR3CN0, #04h ; Timer 3 enabled and interrupt flag cleared
  1885. setb Flag_T3_PENDING
  1886. orl EIE1, #80h ; Enable timer 3 interrupts
  1887. setb IE_EA
  1888. wait_before_zc_scan_exit:
  1889. ret
  1890. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  1891. ;
  1892. ; Wait for comparator to go low/high routines
  1893. ;
  1894. ; Waits for the zero cross scan wait time to elapse
  1895. ; Then scans for comparator going low/high
  1896. ;
  1897. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  1898. wait_for_comp_out_low:
  1899. setb Flag_DEMAG_DETECTED ; Set demag detected flag as default
  1900. mov Comparator_Read_Cnt, #0 ; Reset number of comparator reads
  1901. mov Bit_Access, #00h ; Desired comparator output
  1902. jnb Flag_DIR_CHANGE_BRAKE, ($+6)
  1903. mov Bit_Access, #40h
  1904. sjmp wait_for_comp_out_start
  1905. wait_for_comp_out_high:
  1906. setb Flag_DEMAG_DETECTED ; Set demag detected flag as default
  1907. mov Comparator_Read_Cnt, #0 ; Reset number of comparator reads
  1908. mov Bit_Access, #40h ; Desired comparator output
  1909. jnb Flag_DIR_CHANGE_BRAKE, ($+6)
  1910. mov Bit_Access, #00h
  1911. wait_for_comp_out_start:
  1912. ; Set number of comparator readings
  1913. mov Temp1, #1 ; Number of OK readings required
  1914. mov Temp2, #1 ; Max number of readings required
  1915. jb Flag_HIGH_RPM, comp_scale_samples ; Branch if high rpm
  1916. mov A, Flags_Startup ; Clear demag detected flag if start phases
  1917. jz ($+4)
  1918. clr Flag_DEMAG_DETECTED
  1919. ; Too low value (~<15) causes rough running at pwm harmonics.
  1920. ; Too high a value (~>35) causes the RCT4215 630 to run rough on full throttle
  1921. mov Temp2, #20
  1922. mov A, Comm_Period4x_H ; Set number of readings higher for lower speeds
  1923. clr C
  1924. rrc A
  1925. jnz ($+3)
  1926. inc A
  1927. mov Temp1, A
  1928. clr C
  1929. subb A, #20
  1930. jc ($+4)
  1931. mov Temp1, #20
  1932. jnb Flag_STARTUP_PHASE, comp_scale_samples
  1933. mov Temp1, #27 ; Set many samples during startup, approximately one pwm period
  1934. mov Temp2, #27
  1935. comp_scale_samples:
  1936. IF MCU_48MHZ == 1
  1937. clr C
  1938. mov A, Temp1
  1939. rlc A
  1940. mov Temp1, A
  1941. clr C
  1942. mov A, Temp2
  1943. rlc A
  1944. mov Temp2, A
  1945. ENDIF
  1946. comp_check_timeout:
  1947. jb Flag_T3_PENDING, comp_check_timeout_not_timed_out ; Has zero cross scan timeout elapsed?
  1948. mov A, Comparator_Read_Cnt ; Check that comparator has been read
  1949. jz comp_check_timeout_not_timed_out ; If not read - branch
  1950. jnb Flag_STARTUP_PHASE, comp_check_timeout_timeout_extended ; Extend timeout during startup
  1951. djnz Startup_Zc_Timeout_Cntd, comp_check_timeout_extend_timeout
  1952. comp_check_timeout_timeout_extended:
  1953. setb Flag_COMP_TIMED_OUT
  1954. sjmp setup_comm_wait
  1955. comp_check_timeout_extend_timeout:
  1956. call setup_zc_scan_timeout
  1957. comp_check_timeout_not_timed_out:
  1958. inc Comparator_Read_Cnt ; Increment comparator read count
  1959. Read_Comp_Out ; Read comparator output
  1960. anl A, #40h
  1961. cjne A, Bit_Access, comp_read_wrong
  1962. ; Comp read ok
  1963. mov A, Startup_Cnt ; Force a timeout for the first commutation
  1964. jz wait_for_comp_out_start
  1965. jb Flag_DEMAG_DETECTED, wait_for_comp_out_start ; Do not accept correct comparator output if it is demag
  1966. djnz Temp1, comp_check_timeout ; Decrement readings counter - repeat comparator reading if not zero
  1967. clr Flag_COMP_TIMED_OUT
  1968. sjmp setup_comm_wait
  1969. comp_read_wrong:
  1970. jnb Flag_STARTUP_PHASE, comp_read_wrong_not_startup
  1971. inc Temp1 ; Increment number of OK readings required
  1972. clr C
  1973. mov A, Temp1
  1974. subb A, Temp2 ; If above initial requirement - do not increment further
  1975. jc ($+3)
  1976. dec Temp1
  1977. sjmp comp_check_timeout ; Continue to look for good ones
  1978. comp_read_wrong_not_startup:
  1979. jb Flag_DEMAG_DETECTED, comp_read_wrong_extend_timeout
  1980. inc Temp1 ; Increment number of OK readings required
  1981. clr C
  1982. mov A, Temp1
  1983. subb A, Temp2
  1984. jc comp_check_timeout ; If below initial requirement - take another reading
  1985. sjmp wait_for_comp_out_start ; Otherwise - go back and restart
  1986. comp_read_wrong_extend_timeout:
  1987. clr Flag_DEMAG_DETECTED ; Clear demag detected flag
  1988. anl EIE1, #7Fh ; Disable timer 3 interrupts
  1989. mov TMR3CN0, #00h ; Timer 3 disabled and interrupt flag cleared
  1990. jnb Flag_HIGH_RPM, comp_read_wrong_low_rpm ; Branch if not high rpm
  1991. mov TMR3L, #00h ; Set timeout to ~1ms
  1992. IF MCU_48MHZ == 1
  1993. mov TMR3H, #0F0h
  1994. ELSE
  1995. mov TMR3H, #0F8h
  1996. ENDIF
  1997. comp_read_wrong_timeout_set:
  1998. mov TMR3CN0, #04h ; Timer 3 enabled and interrupt flag cleared
  1999. setb Flag_T3_PENDING
  2000. orl EIE1, #80h ; Enable timer 3 interrupts
  2001. ajmp wait_for_comp_out_start ; If comparator output is not correct - go back and restart
  2002. comp_read_wrong_low_rpm:
  2003. mov A, Comm_Period4x_H ; Set timeout to ~4x comm period 4x value
  2004. mov Temp7, #0FFh ; Default to long
  2005. IF MCU_48MHZ == 1
  2006. clr C
  2007. rlc A
  2008. jc comp_read_wrong_load_timeout
  2009. ENDIF
  2010. clr C
  2011. rlc A
  2012. jc comp_read_wrong_load_timeout
  2013. clr C
  2014. rlc A
  2015. jc comp_read_wrong_load_timeout
  2016. mov Temp7, A
  2017. comp_read_wrong_load_timeout:
  2018. clr C
  2019. clr A
  2020. subb A, Temp7
  2021. mov TMR3L, #0
  2022. mov TMR3H, A
  2023. sjmp comp_read_wrong_timeout_set
  2024. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  2025. ;
  2026. ; Setup commutation timing routine
  2027. ;
  2028. ; Sets up and starts wait from commutation to zero cross
  2029. ;
  2030. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  2031. setup_comm_wait:
  2032. clr IE_EA
  2033. anl EIE1, #7Fh ; Disable timer 3 interrupts
  2034. mov TMR3CN0, #00h ; Timer 3 disabled and interrupt flag cleared
  2035. mov TMR3L, Wt_Comm_Start_L
  2036. mov TMR3H, Wt_Comm_Start_H
  2037. mov TMR3CN0, #04h ; Timer 3 enabled and interrupt flag cleared
  2038. ; Setup next wait time
  2039. mov TMR3RLL, Wt_Adv_Start_L
  2040. mov TMR3RLH, Wt_Adv_Start_H
  2041. setb Flag_T3_PENDING
  2042. orl EIE1, #80h ; Enable timer 3 interrupts
  2043. setb IE_EA ; Enable interrupts again
  2044. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  2045. ;
  2046. ; Evaluate comparator integrity
  2047. ;
  2048. ; Checks comparator signal behaviour versus expected behaviour
  2049. ;
  2050. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  2051. evaluate_comparator_integrity:
  2052. mov A, Flags_Startup
  2053. jz eval_comp_check_timeout
  2054. jb Flag_INITIAL_RUN_PHASE, ($+5) ; Do not increment beyond startup phase
  2055. inc Startup_Cnt ; Increment counter
  2056. sjmp eval_comp_exit
  2057. eval_comp_check_timeout:
  2058. jnb Flag_COMP_TIMED_OUT, eval_comp_exit ; Has timeout elapsed?
  2059. jb Flag_DIR_CHANGE_BRAKE, eval_comp_exit ; Do not exit run mode if it is braking
  2060. jb Flag_DEMAG_DETECTED, eval_comp_exit ; Do not exit run mode if it is a demag situation
  2061. dec SP ; Routine exit without "ret" command
  2062. dec SP
  2063. ljmp run_to_wait_for_power_on_fail ; Yes - exit run mode
  2064. eval_comp_exit:
  2065. ret
  2066. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  2067. ;
  2068. ; Wait for commutation routine
  2069. ;
  2070. ; Waits from zero cross to commutation
  2071. ;
  2072. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  2073. wait_for_comm:
  2074. ; Update demag metric
  2075. mov A, Demag_Detected_Metric ; Sliding average of 8, 256 when demag and 0 when not. Limited to minimum 120
  2076. mov B, #7
  2077. mul AB ; Multiply by 7
  2078. jnb Flag_DEMAG_DETECTED, ($+4) ; Add new value for current demag status
  2079. inc B
  2080. mov C, B.0 ; Divide by 8
  2081. rrc A
  2082. mov C, B.1
  2083. rrc A
  2084. mov C, B.2
  2085. rrc A
  2086. mov Demag_Detected_Metric, A
  2087. clr C
  2088. subb A, #120 ; Limit to minimum 120
  2089. jnc ($+5)
  2090. mov Demag_Detected_Metric, #120
  2091. clr C
  2092. mov A, Demag_Detected_Metric ; Check demag metric
  2093. subb A, Demag_Pwr_Off_Thresh
  2094. jc wait_for_comm_wait ; Cut power if many consecutive demags. This will help retain sync during hard accelerations
  2095. All_pwmFETs_off
  2096. Set_Pwms_Off
  2097. wait_for_comm_wait:
  2098. Wait_For_Timer3
  2099. ; Setup next wait time
  2100. mov TMR3RLL, Wt_Zc_Scan_Start_L
  2101. mov TMR3RLH, Wt_Zc_Scan_Start_H
  2102. setb Flag_T3_PENDING
  2103. orl EIE1, #80h ; Enable timer 3 interrupts
  2104. ret
  2105. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  2106. ;
  2107. ; Commutation routines
  2108. ;
  2109. ; Performs commutation switching
  2110. ;
  2111. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  2112. ; Comm phase 1 to comm phase 2
  2113. comm1comm2:
  2114. Set_RPM_Out
  2115. jb Flag_PGM_DIR_REV, comm12_rev
  2116. clr IE_EA ; Disable all interrupts
  2117. BcomFET_off ; Turn off comfet
  2118. AcomFET_on ; Turn on comfet
  2119. Set_Pwm_C ; To reapply power after a demag cut
  2120. setb IE_EA
  2121. Set_Comp_Phase_B ; Set comparator phase
  2122. ret
  2123. comm12_rev:
  2124. clr IE_EA ; Disable all interrupts
  2125. BcomFET_off ; Turn off comfet
  2126. CcomFET_on ; Turn on comfet (reverse)
  2127. Set_Pwm_A ; To reapply power after a demag cut
  2128. setb IE_EA
  2129. Set_Comp_Phase_B ; Set comparator phase
  2130. ret
  2131. ; Comm phase 2 to comm phase 3
  2132. comm2comm3:
  2133. Clear_RPM_Out
  2134. jb Flag_PGM_DIR_REV, comm23_rev
  2135. clr IE_EA ; Disable all interrupts
  2136. CpwmFET_off ; Turn off pwmfet
  2137. Set_Pwm_B ; To reapply power after a demag cut
  2138. AcomFET_on
  2139. setb IE_EA
  2140. Set_Comp_Phase_C ; Set comparator phase
  2141. ret
  2142. comm23_rev:
  2143. clr IE_EA ; Disable all interrupts
  2144. ApwmFET_off ; Turn off pwmfet (reverse)
  2145. Set_Pwm_B ; To reapply power after a demag cut
  2146. CcomFET_on
  2147. setb IE_EA
  2148. Set_Comp_Phase_A ; Set comparator phase (reverse)
  2149. ret
  2150. ; Comm phase 3 to comm phase 4
  2151. comm3comm4:
  2152. Set_RPM_Out
  2153. jb Flag_PGM_DIR_REV, comm34_rev
  2154. clr IE_EA ; Disable all interrupts
  2155. AcomFET_off ; Turn off comfet
  2156. CcomFET_on ; Turn on comfet
  2157. Set_Pwm_B ; To reapply power after a demag cut
  2158. setb IE_EA
  2159. Set_Comp_Phase_A ; Set comparator phase
  2160. ret
  2161. comm34_rev:
  2162. clr IE_EA ; Disable all interrupts
  2163. CcomFET_off ; Turn off comfet (reverse)
  2164. AcomFET_on ; Turn on comfet (reverse)
  2165. Set_Pwm_B ; To reapply power after a demag cut
  2166. setb IE_EA
  2167. Set_Comp_Phase_C ; Set comparator phase (reverse)
  2168. ret
  2169. ; Comm phase 4 to comm phase 5
  2170. comm4comm5:
  2171. Clear_RPM_Out
  2172. jb Flag_PGM_DIR_REV, comm45_rev
  2173. clr IE_EA ; Disable all interrupts
  2174. BpwmFET_off ; Turn off pwmfet
  2175. Set_Pwm_A ; To reapply power after a demag cut
  2176. CcomFET_on
  2177. setb IE_EA
  2178. Set_Comp_Phase_B ; Set comparator phase
  2179. ret
  2180. comm45_rev:
  2181. clr IE_EA ; Disable all interrupts
  2182. BpwmFET_off ; Turn off pwmfet
  2183. Set_Pwm_C
  2184. AcomFET_on ; To reapply power after a demag cut
  2185. setb IE_EA
  2186. Set_Comp_Phase_B ; Set comparator phase
  2187. ret
  2188. ; Comm phase 5 to comm phase 6
  2189. comm5comm6:
  2190. Set_RPM_Out
  2191. jb Flag_PGM_DIR_REV, comm56_rev
  2192. clr IE_EA ; Disable all interrupts
  2193. CcomFET_off ; Turn off comfet
  2194. BcomFET_on ; Turn on comfet
  2195. Set_Pwm_A ; To reapply power after a demag cut
  2196. setb IE_EA
  2197. Set_Comp_Phase_C ; Set comparator phase
  2198. ret
  2199. comm56_rev:
  2200. clr IE_EA ; Disable all interrupts
  2201. AcomFET_off ; Turn off comfet (reverse)
  2202. BcomFET_on ; Turn on comfet
  2203. Set_Pwm_C ; To reapply power after a demag cut
  2204. setb IE_EA
  2205. Set_Comp_Phase_A ; Set comparator phase (reverse)
  2206. ret
  2207. ; Comm phase 6 to comm phase 1
  2208. comm6comm1:
  2209. Clear_RPM_Out
  2210. jb Flag_PGM_DIR_REV, comm61_rev
  2211. clr IE_EA ; Disable all interrupts
  2212. ApwmFET_off ; Turn off pwmfet
  2213. Set_Pwm_C
  2214. BcomFET_on ; To reapply power after a demag cut
  2215. setb IE_EA
  2216. Set_Comp_Phase_A ; Set comparator phase
  2217. ret
  2218. comm61_rev:
  2219. clr IE_EA ; Disable all interrupts
  2220. CpwmFET_off ; Turn off pwmfet (reverse)
  2221. Set_Pwm_A
  2222. BcomFET_on ; To reapply power after a demag cut
  2223. setb IE_EA
  2224. Set_Comp_Phase_C ; Set comparator phase (reverse)
  2225. ret
  2226. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  2227. ;
  2228. ; Beeper routines (Multiple entry points)
  2229. ;
  2230. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  2231. beep_f1:
  2232. mov Temp3, #66 ; Off wait loop length (Tone)
  2233. mov Temp4, #(3500 / 66) ; Number of beep pulses (Duration)
  2234. sjmp beep
  2235. beep_f2:
  2236. mov Temp3, #45
  2237. mov Temp4, #(3500 / 45)
  2238. sjmp beep
  2239. beep_f3:
  2240. mov Temp3, #38
  2241. mov Temp4, #(3500 / 38)
  2242. sjmp beep
  2243. beep_f4:
  2244. mov Temp3, #25
  2245. mov Temp4, #(3500 / 25)
  2246. sjmp beep
  2247. beep_f5:
  2248. mov Temp3, #20
  2249. mov Temp4, #(3500 / 25)
  2250. sjmp beep
  2251. beep_f1_short:
  2252. mov Temp3, #66
  2253. mov Temp4, #(2000 / 66)
  2254. sjmp beep
  2255. beep_f2_short:
  2256. mov Temp3, #45
  2257. mov Temp4, #(2000 / 45)
  2258. sjmp beep
  2259. beep:
  2260. mov A, Beep_Strength
  2261. djnz ACC, beep_start ; Start if beep strength is not 1
  2262. ret
  2263. beep_start:
  2264. mov Temp2, #2
  2265. beep_onoff:
  2266. clr A
  2267. BcomFET_off ; BcomFET off
  2268. djnz ACC, $ ; Allow some time after comfet is turned off
  2269. BpwmFET_on ; BpwmFET on (in order to charge the driver of the BcomFET)
  2270. djnz ACC, $ ; Let the pwmfet be turned on a while
  2271. BpwmFET_off ; BpwmFET off again
  2272. djnz ACC, $ ; Allow some time after pwmfet is turned off
  2273. BcomFET_on ; BcomFET on
  2274. djnz ACC, $ ; Allow some time after comfet is turned on
  2275. ; Turn on pwmfet
  2276. mov A, Temp2
  2277. jb ACC.0, beep_apwmfet_on
  2278. ApwmFET_on
  2279. beep_apwmfet_on:
  2280. jnb ACC.0, beep_cpwmfet_on
  2281. CpwmFET_on
  2282. beep_cpwmfet_on:
  2283. mov A, Beep_Strength
  2284. djnz ACC, $
  2285. ; Turn off pwmfet
  2286. mov A, Temp2
  2287. jb ACC.0, beep_apwmfet_off
  2288. ApwmFET_off
  2289. beep_apwmfet_off:
  2290. jnb ACC.0, beep_cpwmfet_off
  2291. CpwmFET_off
  2292. beep_cpwmfet_off:
  2293. mov A, #150 ; 25us off
  2294. djnz ACC, $
  2295. djnz Temp2, beep_onoff
  2296. ; Copy variable
  2297. mov A, Temp3
  2298. mov Temp1, A
  2299. beep_off: ; Fets off loop
  2300. mov A, #150
  2301. djnz ACC, $
  2302. djnz Temp1, beep_off
  2303. djnz Temp4, beep_start
  2304. BcomFET_off
  2305. ret
  2306. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  2307. ;
  2308. ; Switch power off routine
  2309. ;
  2310. ; Switches all fets off
  2311. ;
  2312. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  2313. switch_power_off:
  2314. All_pwmFETs_Off ; Turn off all pwm fets
  2315. All_comFETs_Off ; Turn off all commutation fets
  2316. Set_Pwms_Off
  2317. ret
  2318. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  2319. ;
  2320. ; Set default parameters
  2321. ;
  2322. ; Sets default programming parameters
  2323. ;
  2324. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  2325. set_default_parameters:
  2326. mov Temp1, #_Pgm_Gov_P_Gain
  2327. Push_Mem Temp1, #0FFh ; _Pgm_Gov_P_Gain
  2328. Push_Mem Temp1, #0FFh ; _Pgm_Gov_I_Gain
  2329. Push_Mem Temp1, #0FFh ; _Pgm_Gov_Mode
  2330. Push_Mem Temp1, #0FFh ; _Pgm_Low_Voltage_Lim
  2331. Push_Mem Temp1, #0FFh ; _Pgm_Motor_Gain
  2332. Push_Mem Temp1, #0FFh ; _Pgm_Motor_Idle
  2333. Push_Mem Temp1, #DEFAULT_PGM_STARTUP_PWR ; Pgm_Startup_Pwr
  2334. Push_Mem Temp1, #0FFh ; _Pgm_Pwm_Freq
  2335. Push_Mem Temp1, #DEFAULT_PGM_DIRECTION ; Pgm_Direction
  2336. Push_Mem Temp1, #0FFh ; _Pgm_Input_Pol
  2337. inc Temp1 ; Skip Initialized_L_Dummy
  2338. inc Temp1 ; Skip Initialized_H_Dummy
  2339. Push_Mem Temp1, #0FFh ; _Pgm_Enable_TX_Program
  2340. Push_Mem Temp1, #0FFh ; _Pgm_Main_Rearm_Start
  2341. Push_Mem Temp1, #0FFh ; _Pgm_Gov_Setup_Target
  2342. Push_Mem Temp1, #0FFh ; _Pgm_Startup_Rpm
  2343. Push_Mem Temp1, #0FFh ; _Pgm_Startup_Accel
  2344. Push_Mem Temp1, #0FFh ; _Pgm_Volt_Comp
  2345. Push_Mem Temp1, #DEFAULT_PGM_COMM_TIMING ; Pgm_Comm_Timing
  2346. Push_Mem Temp1, #0FFh ; _Pgm_Damping_Force
  2347. Push_Mem Temp1, #0FFh ; _Pgm_Gov_Range
  2348. Push_Mem Temp1, #0FFh ; _Pgm_Startup_Method
  2349. Push_Mem Temp1, #0FFh ; _Pgm_Min_Throttle
  2350. Push_Mem Temp1, #0FFh ; _Pgm_Max_Throttle
  2351. Push_Mem Temp1, #DEFAULT_PGM_BEEP_STRENGTH ; Pgm_Beep_Strength
  2352. Push_Mem Temp1, #DEFAULT_PGM_BEACON_STRENGTH ; Pgm_Beacon_Strength
  2353. Push_Mem Temp1, #DEFAULT_PGM_BEACON_DELAY ; Pgm_Beacon_Delay
  2354. Push_Mem Temp1, #0FFh ; _Pgm_Throttle_Rate
  2355. Push_Mem Temp1, #DEFAULT_PGM_DEMAG_COMP ; Pgm_Demag_Comp
  2356. Push_Mem Temp1, #0FFh ; _Pgm_BEC_Voltage_High
  2357. Push_Mem Temp1, #0FFh ; _Pgm_Center_Throttle
  2358. Push_Mem Temp1, #0FFh ; _Pgm_Main_Spoolup_Time
  2359. Push_Mem Temp1, #DEFAULT_PGM_ENABLE_TEMP_PROT ; Pgm_Enable_Temp_Prot
  2360. Push_Mem Temp1, #DEFAULT_PGM_ENABLE_POWER_PROT ; Pgm_Enable_Power_Prot
  2361. Push_Mem Temp1, #0FFh ; _Pgm_Enable_Pwm_Input
  2362. Push_Mem Temp1, #0FFh ; _Pgm_Pwm_Dither
  2363. Push_Mem Temp1, #DEFAULT_PGM_BRAKE_ON_STOP ; Pgm_Brake_On_Stop
  2364. Push_Mem Temp1, #DEFAULT_PGM_LED_CONTROL ; Pgm_LED_Control
  2365. ret
  2366. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  2367. ;
  2368. ; Decode settings
  2369. ;
  2370. ; Decodes various settings
  2371. ;
  2372. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  2373. decode_settings:
  2374. ; Load programmed direction
  2375. mov Temp1, #Pgm_Direction
  2376. mov A, @Temp1
  2377. clr C
  2378. subb A, #3
  2379. setb Flag_PGM_BIDIR
  2380. jnc ($+4)
  2381. clr Flag_PGM_BIDIR
  2382. clr Flag_PGM_DIR_REV
  2383. mov A, @Temp1
  2384. jnb ACC.1, ($+5)
  2385. setb Flag_PGM_DIR_REV
  2386. mov C, Flag_PGM_DIR_REV
  2387. mov Flag_PGM_BIDIR_REV, C
  2388. ; Decode startup power
  2389. mov Temp1, #Pgm_Startup_Pwr
  2390. mov A, @Temp1
  2391. dec A
  2392. mov DPTR, #STARTUP_POWER_TABLE
  2393. movc A, @A+DPTR
  2394. mov Temp1, #Pgm_Startup_Pwr_Decoded
  2395. mov @Temp1, A
  2396. ; Decode low rpm power slope
  2397. mov Temp1, #Pgm_Startup_Pwr
  2398. mov A, @Temp1
  2399. mov Low_Rpm_Pwr_Slope, A
  2400. clr C
  2401. subb A, #2
  2402. jnc ($+5)
  2403. mov Low_Rpm_Pwr_Slope, #2
  2404. ; Decode demag compensation
  2405. mov Temp1, #Pgm_Demag_Comp
  2406. mov A, @Temp1
  2407. mov Demag_Pwr_Off_Thresh, #255 ; Set default
  2408. cjne A, #2, decode_demag_high
  2409. mov Demag_Pwr_Off_Thresh, #160 ; Settings for demag comp low
  2410. decode_demag_high:
  2411. cjne A, #3, decode_demag_done
  2412. mov Demag_Pwr_Off_Thresh, #130 ; Settings for demag comp high
  2413. decode_demag_done:
  2414. ; Decode temperature protection limit
  2415. mov Temp1, #Pgm_Enable_Temp_Prot
  2416. mov A, @Temp1
  2417. mov Temp1, A
  2418. jz decode_temp_done
  2419. mov A, #(TEMP_LIMIT-TEMP_LIMIT_STEP)
  2420. decode_temp_step:
  2421. add A, #TEMP_LIMIT_STEP
  2422. djnz Temp1, decode_temp_step
  2423. decode_temp_done:
  2424. mov Temp_Prot_Limit, A
  2425. ; Dithering
  2426. IF PWM_BITS_H == 1
  2427. mov Temp1, #Dithering_Patterns
  2428. Push_Mem Temp1, #00h
  2429. Push_Mem Temp1, #55h
  2430. ELSEIF PWM_BITS_H == 0
  2431. mov Temp1, #Dithering_Patterns
  2432. Push_Mem Temp1, #00h
  2433. Push_Mem Temp1, #11h
  2434. Push_Mem Temp1, #55h
  2435. Push_Mem Temp1, #77h
  2436. ENDIF
  2437. ret
  2438. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  2439. ;
  2440. ; Detect DShot RCP level
  2441. ;
  2442. ; Determine if RCP signal level is normal or inverted DShot
  2443. ;
  2444. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  2445. detect_rcp_level:
  2446. mov A, #100 ; Must repeat the same level 100 times in a row
  2447. mov C, RTX_PORT.RTX_PIN
  2448. detect_rcp_level_read:
  2449. jc ($+5)
  2450. jb RTX_PORT.RTX_PIN, detect_rcp_level ; Level changed from low to high - start over
  2451. jnc ($+5)
  2452. jnb RTX_PORT.RTX_PIN, detect_rcp_level ; Level changed from high to low - start over
  2453. djnz ACC, detect_rcp_level_read
  2454. mov Flag_RCP_DSHOT_INVERTED, C
  2455. ret
  2456. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  2457. ;
  2458. ; LED control
  2459. ;
  2460. ; Controls LEDs
  2461. ;
  2462. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  2463. led_control:
  2464. mov Temp1, #Pgm_LED_Control
  2465. mov A, @Temp1
  2466. mov Temp2, A
  2467. anl A, #03h
  2468. Set_LED_0
  2469. jnz led_0_done
  2470. Clear_LED_0
  2471. led_0_done:
  2472. mov A, Temp2
  2473. anl A, #0Ch
  2474. Set_LED_1
  2475. jnz led_1_done
  2476. Clear_LED_1
  2477. led_1_done:
  2478. mov A, Temp2
  2479. anl A, #030h
  2480. Set_LED_2
  2481. jnz led_2_done
  2482. Clear_LED_2
  2483. led_2_done:
  2484. mov A, Temp2
  2485. anl A, #0C0h
  2486. Set_LED_3
  2487. jnz led_3_done
  2488. Clear_LED_3
  2489. led_3_done:
  2490. ret
  2491. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  2492. ;
  2493. ; Check DShot command
  2494. ;
  2495. ; Determine received DShot command and perform action
  2496. ;
  2497. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  2498. dshot_cmd_check:
  2499. mov A, Dshot_Cmd
  2500. jz dshot_cmd_exit_no_clear
  2501. mov Temp1, A
  2502. clr C
  2503. subb A, #6 ; Beacon beeps for command 1-5
  2504. jnc dshot_cmd_direction_1
  2505. call beacon_beep
  2506. sjmp dshot_cmd_exit
  2507. dshot_cmd_direction_1:
  2508. ; Change programmed motor direction to normal
  2509. cjne Temp1, #7, dshot_cmd_direction_2
  2510. clr C
  2511. mov A, Dshot_Cmd_Cnt
  2512. subb A, #6 ; Needs to receive it 6 times in a row
  2513. jc dshot_cmd_exit_no_clear
  2514. mov A, #1
  2515. jnb Flag_PGM_BIDIR, ($+5)
  2516. mov A, #3
  2517. mov Temp1, #Pgm_Direction
  2518. mov @Temp1, A
  2519. clr Flag_PGM_DIR_REV
  2520. clr Flag_PGM_BIDIR_REV
  2521. sjmp dshot_cmd_exit
  2522. dshot_cmd_direction_2:
  2523. ; Change programmed motor direction to reversed
  2524. cjne Temp1, #8, dshot_cmd_direction_bidir_off
  2525. clr C
  2526. mov A, Dshot_Cmd_Cnt
  2527. subb A, #6 ; Needs to receive it 6 times in a row
  2528. jc dshot_cmd_exit_no_clear
  2529. mov A, #2
  2530. jnb Flag_PGM_BIDIR, ($+5)
  2531. mov A, #4
  2532. mov Temp1, #Pgm_Direction
  2533. mov @Temp1, A
  2534. setb Flag_PGM_DIR_REV
  2535. setb Flag_PGM_BIDIR_REV
  2536. sjmp dshot_cmd_exit
  2537. dshot_cmd_direction_bidir_off:
  2538. ; Change programmed motor mode to normal (not bidirectional)
  2539. cjne Temp1, #9, dshot_cmd_direction_bidir_on
  2540. clr C
  2541. mov A, Dshot_Cmd_Cnt
  2542. subb A, #6 ; Needs to receive it 6 times in a row
  2543. jc dshot_cmd_exit_no_clear
  2544. jnb Flag_PGM_BIDIR, dshot_cmd_exit
  2545. clr C
  2546. mov Temp1, #Pgm_Direction
  2547. mov A, @Temp1
  2548. subb A, #2
  2549. mov @Temp1, A
  2550. clr Flag_PGM_BIDIR
  2551. sjmp dshot_cmd_exit
  2552. dshot_cmd_direction_bidir_on:
  2553. ; Change programmed motor mode to bidirectional
  2554. cjne Temp1, #10, dshot_cmd_direction_normal
  2555. clr C
  2556. mov A, Dshot_Cmd_Cnt
  2557. subb A, #6 ; Needs to receive it 6 times in a row
  2558. jc dshot_cmd_exit_no_clear
  2559. jb Flag_PGM_BIDIR, dshot_cmd_exit
  2560. mov Temp1, #Pgm_Direction
  2561. mov A, @Temp1
  2562. add A, #2
  2563. mov @Temp1, A
  2564. setb Flag_PGM_BIDIR
  2565. dshot_cmd_exit:
  2566. mov Dshot_Cmd, #0
  2567. mov Dshot_Cmd_Cnt, #0
  2568. dshot_cmd_exit_no_clear:
  2569. ret
  2570. dshot_cmd_direction_normal:
  2571. ; Change programmed motor direction to that stored in eeprom
  2572. cjne Temp1, #20, dshot_cmd_direction_reverse
  2573. clr C
  2574. mov A, Dshot_Cmd_Cnt
  2575. subb A, #6 ; Needs to receive it 6 times in a row
  2576. jc dshot_cmd_exit_no_clear
  2577. clr IE_EA ; DPTR used in interrupts
  2578. mov DPTR, #Eep_Pgm_Direction ; Read from flash
  2579. mov A, #0
  2580. movc A, @A+DPTR
  2581. setb IE_EA
  2582. mov Temp1, #Pgm_Direction
  2583. mov @Temp1, A
  2584. rrc A ; Lsb to carry
  2585. clr Flag_PGM_DIR_REV
  2586. clr Flag_PGM_BIDIR_REV
  2587. jc ($+4)
  2588. setb Flag_PGM_DIR_REV
  2589. jc ($+4)
  2590. setb Flag_PGM_BIDIR_REV
  2591. sjmp dshot_cmd_exit
  2592. dshot_cmd_direction_reverse: ; Temporary reverse
  2593. ; Change programmed motor direction to the reverse of what is stored in eeprom
  2594. cjne Temp1, #21, dshot_cmd_save_settings
  2595. clr C
  2596. mov A, Dshot_Cmd_Cnt
  2597. subb A, #6 ; Needs to receive it 6 times in a row
  2598. jc dshot_cmd_exit_no_clear
  2599. clr IE_EA ; DPTR used in interrupts
  2600. mov DPTR, #Eep_Pgm_Direction ; Read from flash
  2601. mov A, #0
  2602. movc A, @A+DPTR
  2603. setb IE_EA
  2604. mov Temp1, A
  2605. cjne Temp1, #1, ($+5)
  2606. mov A, #2
  2607. cjne Temp1, #2, ($+5)
  2608. mov A, #1
  2609. cjne Temp1, #3, ($+5)
  2610. mov A, #4
  2611. cjne Temp1, #4, ($+5)
  2612. mov A, #3
  2613. mov Temp1, #Pgm_Direction
  2614. mov @Temp1, A
  2615. rrc A ; Lsb to carry
  2616. clr Flag_PGM_DIR_REV
  2617. clr Flag_PGM_BIDIR_REV
  2618. jc ($+4)
  2619. setb Flag_PGM_DIR_REV
  2620. jc ($+4)
  2621. setb Flag_PGM_BIDIR_REV
  2622. sjmp dshot_cmd_exit
  2623. dshot_cmd_save_settings:
  2624. cjne Temp1, #12, dshot_cmd_exit
  2625. clr C
  2626. mov A, Dshot_Cmd_Cnt
  2627. subb A, #6 ; Needs to receive it 6 times in a row
  2628. jc dshot_cmd_exit_no_clear
  2629. mov Flash_Key_1, #0A5h ; Initialize flash keys to valid values
  2630. mov Flash_Key_2, #0F1h
  2631. call erase_and_store_all_in_eeprom
  2632. mov Flash_Key_1, #0 ; Initialize flash keys to invalid values
  2633. mov Flash_Key_2, #0
  2634. setb IE_EA
  2635. jmp dshot_cmd_exit
  2636. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  2637. ;
  2638. ; DShot beacon beep
  2639. ;
  2640. ; Beep with beacon strength
  2641. ; Beep type 1-5 in Temp1
  2642. ;
  2643. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  2644. beacon_beep:
  2645. clr IE_EA
  2646. call switch_power_off ; Switch power off in case braking is set
  2647. mov Temp2, #Pgm_Beacon_Strength
  2648. mov Beep_Strength, @Temp2
  2649. cjne Temp1, #1, beacon_beep2
  2650. call beep_f1
  2651. sjmp beacon_beep_exit
  2652. beacon_beep2:
  2653. cjne Temp1, #2, beacon_beep3
  2654. call beep_f2
  2655. sjmp beacon_beep_exit
  2656. beacon_beep3:
  2657. cjne Temp1, #3, beacon_beep4
  2658. call beep_f3
  2659. sjmp beacon_beep_exit
  2660. beacon_beep4:
  2661. cjne Temp1, #4, beacon_beep5
  2662. call beep_f4
  2663. sjmp beacon_beep_exit
  2664. beacon_beep5:
  2665. call beep_f5
  2666. beacon_beep_exit:
  2667. mov Temp2, #Pgm_Beep_Strength
  2668. mov Beep_Strength, @Temp2
  2669. setb IE_EA
  2670. call wait100ms
  2671. ret
  2672. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  2673. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  2674. ;
  2675. ; Main program start
  2676. ;
  2677. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  2678. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  2679. pgm_start:
  2680. ; Initialize flash keys to invalid values
  2681. mov Flash_Key_1, #0
  2682. mov Flash_Key_2, #0
  2683. ; Disable the WDT
  2684. mov WDTCN, #0DEh ; Disable watchdog
  2685. mov WDTCN, #0ADh
  2686. ; Initialize stack
  2687. mov SP, #Stack ; 16 bytes of indirect RAM
  2688. ; Initialize VDD monitor
  2689. orl VDM0CN, #080h ; Enable the VDD monitor
  2690. mov RSTSRC, #06h ; Set missing clock and VDD monitor as a reset source if not 1S capable
  2691. ; Set clock frequency
  2692. mov CLKSEL, #00h ; Set clock divider to 1
  2693. ; Switch power off
  2694. call switch_power_off
  2695. ; Ports initialization
  2696. mov P0, #P0_INIT
  2697. mov P0MDIN, #P0_DIGITAL
  2698. mov P0MDOUT, #P0_PUSHPULL
  2699. mov P0, #P0_INIT
  2700. mov P0SKIP, #P0_SKIP
  2701. mov P1, #P1_INIT
  2702. mov P1MDIN, #P1_DIGITAL
  2703. mov P1MDOUT, #P1_PUSHPULL
  2704. mov P1, #P1_INIT
  2705. mov P1SKIP, #P1_SKIP
  2706. mov P2MDOUT, #P2_PUSHPULL
  2707. ; Initialize the XBAR and related functionality
  2708. Initialize_Xbar
  2709. ; Switch power off again, after initializing ports
  2710. call switch_power_off
  2711. ; Clear RAM
  2712. clr A ; Clear accumulator
  2713. mov Temp1, A ; Clear Temp1
  2714. clear_ram:
  2715. mov @Temp1, A ; Clear RAM
  2716. djnz Temp1, clear_ram ; Is A not zero? - jump
  2717. ; Set default programmed parameters
  2718. call set_default_parameters
  2719. ; Read all programmed parameters
  2720. call read_all_eeprom_parameters
  2721. ; Set beep strength
  2722. mov Temp1, #Pgm_Beep_Strength
  2723. mov Beep_Strength, @Temp1
  2724. ; Initializing beep
  2725. clr IE_EA ; Disable interrupts explicitly
  2726. call wait200ms
  2727. call beep_f1
  2728. call wait10ms
  2729. call beep_f2
  2730. call wait10ms
  2731. call beep_f1
  2732. call wait10ms
  2733. call beep_f3
  2734. call wait200ms
  2735. call beep_f2
  2736. call beep_f4
  2737. call beep_f4
  2738. call led_control
  2739. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  2740. ;
  2741. ; No signal entry point
  2742. ;
  2743. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  2744. init_no_signal:
  2745. ; Disable interrupts explicitly
  2746. clr IE_EA
  2747. ; Initialize flash keys to invalid values
  2748. mov Flash_Key_1, #0
  2749. mov Flash_Key_2, #0
  2750. ; Check if input signal is high for more than 15ms
  2751. mov Temp1, #250
  2752. input_high_check_1:
  2753. mov Temp2, #250
  2754. input_high_check_2:
  2755. jnb RTX_PORT.RTX_PIN, bootloader_done ; Look for low
  2756. djnz Temp2, input_high_check_2
  2757. djnz Temp1, input_high_check_1
  2758. ljmp 1C00h ; Jump to bootloader
  2759. bootloader_done:
  2760. ; Decode settings
  2761. call decode_settings
  2762. ; Set beep strength
  2763. mov Temp1, #Pgm_Beep_Strength
  2764. mov Beep_Strength, @Temp1
  2765. ; Switch power off
  2766. call switch_power_off
  2767. ; Set clock frequency
  2768. IF MCU_48MHZ == 1
  2769. Set_MCU_Clk_24MHz
  2770. ENDIF
  2771. ; Setup timers for DShot
  2772. mov TCON, #51h ; Timer 0/1 run and INT0 edge triggered
  2773. mov CKCON0, #01h ; Timer 0/1 clock is system clock divided by 4 (for DShot150)
  2774. mov TMOD, #0AAh ; Timer 0/1 set to 8bits auto reload and gated by INT0/1
  2775. mov TH0, #0 ; Auto reload value zero
  2776. mov TH1, #0
  2777. mov TMR2CN0, #04h ; Timer 2 enabled
  2778. mov TMR3CN0, #04h ; Timer 3 enabled
  2779. Initialize_PCA ; Initialize PCA
  2780. Set_Pwm_Polarity ; Set pwm polarity
  2781. Enable_Power_Pwm_Module ; Enable power pwm module
  2782. Enable_Damp_Pwm_Module ; Enable damping pwm module
  2783. Initialize_Comparator ; Initialize comparator
  2784. Initialize_Adc ; Initialize ADC operation
  2785. call wait1ms
  2786. mov Stall_Cnt, #0 ; Reset stall count
  2787. mov Dshot_Cmd, #0 ; Clear DShot command
  2788. mov Dshot_Cmd_Cnt, #0 ; Clear DShot command count
  2789. ; Setup RCP for DShot
  2790. call detect_rcp_level ; Detect normal or inverted DShot
  2791. ; Route RCP according to detected DShot signal (normal or inverted)
  2792. mov IT01CF, #(80h + (RTX_PIN SHL 4) + RTX_PIN) ; Route RCP input to INT0/1, with INT1 inverted
  2793. jnb Flag_RCP_DSHOT_INVERTED, ($+6)
  2794. mov IT01CF, #(08h + (RTX_PIN SHL 4) + RTX_PIN) ; Route RCP input to INT0/1, with INT0 inverted
  2795. ; Setup interrupts for DShot
  2796. mov IE, #2Dh ; Enable timer 1/2 interrupts and INT0/1 interrupts
  2797. mov EIE1, #90h ; Enable timer 3 and PCA0 interrupts
  2798. mov IP, #03h ; High priority to timer 0 and INT0 interrupts
  2799. setb IE_EA ; Enable all interrupts
  2800. call wait200ms
  2801. ; Setup variables for DShot150
  2802. ; TODO: dshot150 not supported for now
  2803. ; IF MCU_48MHZ == 1
  2804. ; mov DShot_Timer_Preset, #128 ; Load DShot sync timer preset (for DShot150)
  2805. ; ELSE
  2806. ; mov DShot_Timer_Preset, #192
  2807. ; ENDIF
  2808. ; ; TODO: we cannot currently support DShot150 on 48MHz (because of DShot_Frame_Length_Thr)
  2809. ; IF MCU_48MHZ == 0
  2810. ; mov DShot_Pwm_Thr, #10 ; Load DShot qualification pwm threshold (for DShot150)
  2811. ; mov DShot_Frame_Length_Thr, #160 ; Load DShot frame length criteria
  2812. ; Set_DShot_Tlm_Bitrate 187500 ; = 5/4 * 150000
  2813. ; ; Test whether signal is DShot150
  2814. ; mov Rcp_Outside_Range_Cnt, #10 ; Set out of range counter
  2815. ; call wait100ms ; Wait for new RC pulse
  2816. ; mov DShot_Pwm_Thr, #8 ; Load DShot regular pwm threshold
  2817. ; clr C
  2818. ; mov A, Rcp_Outside_Range_Cnt ; Check if pulses were accepted
  2819. ; subb A, #10
  2820. ; mov Dshot_Cmd, #0
  2821. ; mov Dshot_Cmd_Cnt, #0
  2822. ; jc arming_begin
  2823. ; ENDIF
  2824. mov CKCON0, #0Ch ; Timer 0/1 clock is system clock (for DShot300/600)
  2825. ; Setup variables for DShot300
  2826. IF MCU_48MHZ == 1
  2827. mov DShot_Timer_Preset, #0 ; Load DShot sync timer preset (for DShot300)
  2828. ELSE
  2829. mov DShot_Timer_Preset, #128
  2830. ENDIF
  2831. mov DShot_Pwm_Thr, #20 ; Load DShot qualification pwm threshold (for DShot300)
  2832. mov DShot_Frame_Length_Thr, #80 ; Load DShot frame length criteria
  2833. Set_DShot_Tlm_Bitrate 375000 ; = 5/4 * 300000
  2834. ; Test whether signal is DShot300
  2835. mov Rcp_Outside_Range_Cnt, #10 ; Set out of range counter
  2836. call wait100ms ; Wait for new RC pulse
  2837. mov DShot_Pwm_Thr, #16 ; Load DShot regular pwm threshold
  2838. clr C
  2839. mov A, Rcp_Outside_Range_Cnt ; Check if pulses were accepted
  2840. subb A, #10
  2841. mov Dshot_Cmd, #0
  2842. mov Dshot_Cmd_Cnt, #0
  2843. jc arming_begin
  2844. ; Setup variables for DShot600
  2845. IF MCU_48MHZ == 1
  2846. mov DShot_Timer_Preset, #128 ; Load DShot sync timer preset (for DShot600)
  2847. ELSE
  2848. mov DShot_Timer_Preset, #192
  2849. ENDIF
  2850. mov DShot_Pwm_Thr, #10 ; Load DShot qualification pwm threshold (for DShot600)
  2851. mov DShot_Frame_Length_Thr, #40 ; Load DShot frame length criteria
  2852. Set_DShot_Tlm_Bitrate 750000 ; = 5/4 * 600000
  2853. ; Test whether signal is DShot600
  2854. mov Rcp_Outside_Range_Cnt, #10 ; Set out of range counter
  2855. call wait100ms ; Wait for new RC pulse
  2856. mov DShot_Pwm_Thr, #8 ; Load DShot regular pwm threshold
  2857. clr C
  2858. mov A, Rcp_Outside_Range_Cnt ; Check if pulses were accepted
  2859. subb A, #10
  2860. mov Dshot_Cmd, #0
  2861. mov Dshot_Cmd_Cnt, #0
  2862. jc arming_begin
  2863. ajmp init_no_signal
  2864. arming_begin:
  2865. ; Beep arm sequence start signal
  2866. clr IE_EA ; Disable all interrupts
  2867. call beep_f1_short ; Signal that RC pulse is ready
  2868. setb IE_EA ; Enable all interrupts
  2869. ; Arming sequence start
  2870. arming_wait:
  2871. call wait100ms ; Wait for new throttle value
  2872. jnb Flag_RCP_STOP, arming_wait ; Start over if not below stop
  2873. ; Beep arm sequence end signal
  2874. clr IE_EA ; Disable all interrupts
  2875. call beep_f2_short ; Signal that ESC is armed
  2876. setb IE_EA ; Enable all interrupts
  2877. call wait200ms
  2878. ; Armed and waiting for power on
  2879. wait_for_power_on:
  2880. clr A
  2881. mov Comm_Period4x_L, A ; Reset commutation period for telemetry
  2882. mov Comm_Period4x_H, A
  2883. mov Power_On_Wait_Cnt_L, A ; Clear wait counter
  2884. mov Power_On_Wait_Cnt_H, A
  2885. wait_for_power_on_loop:
  2886. inc Power_On_Wait_Cnt_L ; Increment low wait counter
  2887. mov A, Power_On_Wait_Cnt_L
  2888. cpl A
  2889. jnz wait_for_power_on_no_beep ; Counter wrapping (about 3 sec)
  2890. inc Power_On_Wait_Cnt_H ; Increment high wait counter
  2891. mov Temp1, #Pgm_Beacon_Delay
  2892. mov A, @Temp1
  2893. mov Temp1, #25 ; Approximately 1 min
  2894. dec A
  2895. jz beep_delay_set
  2896. mov Temp1, #50 ; Approximately 2 min
  2897. dec A
  2898. jz beep_delay_set
  2899. mov Temp1, #125 ; Approximately 5 min
  2900. dec A
  2901. jz beep_delay_set
  2902. mov Temp1, #250 ; Approximately 10 min
  2903. dec A
  2904. jz beep_delay_set
  2905. mov Power_On_Wait_Cnt_H, #0 ; Reset counter for infinite delay
  2906. beep_delay_set:
  2907. clr C
  2908. mov A, Power_On_Wait_Cnt_H
  2909. subb A, Temp1 ; Check against chosen delay
  2910. jc wait_for_power_on_no_beep ; Has delay elapsed?
  2911. call switch_power_off ; Switch power off in case braking is set
  2912. call wait1ms
  2913. dec Power_On_Wait_Cnt_H ; Decrement high wait counter
  2914. mov Power_On_Wait_Cnt_L, #0 ; Set low wait counter
  2915. mov Temp1, #Pgm_Beacon_Strength
  2916. mov Beep_Strength, @Temp1
  2917. clr IE_EA ; Disable all interrupts
  2918. call beep_f4 ; Signal that there is no signal
  2919. setb IE_EA ; Enable all interrupts
  2920. mov Temp1, #Pgm_Beep_Strength
  2921. mov Beep_Strength, @Temp1
  2922. call wait100ms ; Wait for new RC pulse to be measured
  2923. wait_for_power_on_no_beep:
  2924. jb Flag_PACKET_PENDING, wait_for_power_telemetry_done
  2925. setb Flag_T3_PENDING ; Set flag temporarily to avoid early return
  2926. call dshot_tlm_create_packet
  2927. clr Flag_T3_PENDING
  2928. wait_for_power_telemetry_done:
  2929. call wait10ms
  2930. mov A, Rcp_Timeout_Cntd ; Load RC pulse timeout counter value
  2931. jnz wait_for_power_on_not_missing ; If it is not zero - proceed
  2932. ajmp init_no_signal ; If pulses missing - go back to detect input signal
  2933. wait_for_power_on_not_missing:
  2934. jnb Flag_RCP_STOP, wait_for_power_on_nonzero ; Higher than stop, Yes - proceed
  2935. mov A, Dshot_Cmd
  2936. jz wait_for_power_on_loop ; Check DShot command if not zero, otherwise wait for power
  2937. call dshot_cmd_check
  2938. sjmp wait_for_power_on_not_missing ; Check dshot command again, in case command needs to be received multiple times
  2939. wait_for_power_on_nonzero:
  2940. call wait100ms ; Wait to see if start pulse was only a glitch
  2941. mov A, Rcp_Timeout_Cntd ; Load RC pulse timeout counter value
  2942. jnz ($+5) ; If it is not zero - proceed
  2943. ajmp init_no_signal ; If it is zero (pulses missing) - go back to detect input signal
  2944. mov Dshot_Cmd, #0
  2945. mov Dshot_Cmd_Cnt, #0
  2946. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  2947. ;
  2948. ; Start entry point
  2949. ;
  2950. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  2951. init_start:
  2952. clr IE_EA
  2953. call switch_power_off
  2954. clr A
  2955. setb IE_EA
  2956. clr A
  2957. mov Adc_Conversion_Cnt, A
  2958. mov Flags0, A ; Clear flags0
  2959. mov Flags1, A ; Clear flags1
  2960. mov Flags_Startup, A ; Clear startup flags
  2961. mov Demag_Detected_Metric, A ; Clear demag metric
  2962. ;**** **** **** **** ****
  2963. ; Motor start beginning
  2964. ;**** **** **** **** ****
  2965. mov Adc_Conversion_Cnt, #8 ; Make sure a temp reading is done
  2966. call wait1ms
  2967. Start_Adc ; Start adc conversion
  2968. read_initial_temp:
  2969. jnb ADC0CN0_ADINT, read_initial_temp
  2970. Read_Adc_Result ; Read initial temperature
  2971. mov A, Temp2
  2972. jnz ($+3) ; Is reading below 256?
  2973. mov Temp1, A ; Yes - set average temperature value to zero
  2974. mov Current_Average_Temp, Temp1 ; Set initial average temperature
  2975. call check_temp_voltage_and_limit_power
  2976. mov Adc_Conversion_Cnt, #8 ; Make sure a temp reading is done next time
  2977. ; Set up start operating conditions
  2978. clr IE_EA ; Disable interrupts
  2979. ; Adjust startup power
  2980. mov Temp2, #Pgm_Startup_Pwr_Decoded
  2981. mov Pwm_Limit_Beg, @Temp2 ; Set initial pwm limit
  2982. mov Pwm_Limit, Pwm_Limit_Beg
  2983. mov Pwm_Limit_By_Rpm, Pwm_Limit_Beg
  2984. setb IE_EA
  2985. ; Begin startup sequence
  2986. IF MCU_48MHZ == 1
  2987. Set_MCU_Clk_48MHz
  2988. ; Scale DShot criteria for 48MHz
  2989. clr C
  2990. mov A, DShot_Frame_Length_Thr ; Scale frame length criteria
  2991. rlc A
  2992. mov DShot_Frame_Length_Thr, A
  2993. clr C
  2994. mov A, DShot_Pwm_Thr ; Scale pulse width criteria
  2995. rlc A
  2996. mov DShot_Pwm_Thr, A
  2997. ; Scale DShot telemetry for 24MHz
  2998. mov A, DShot_GCR_Pulse_Time_1
  2999. xch A, DShot_GCR_Pulse_Time_1_Tmp
  3000. mov DShot_GCR_Pulse_Time_1, A
  3001. mov A, DShot_GCR_Pulse_Time_2
  3002. xch A, DShot_GCR_Pulse_Time_2_Tmp
  3003. mov DShot_GCR_Pulse_Time_2, A
  3004. mov A, DShot_GCR_Pulse_Time_3
  3005. xch A, DShot_GCR_Pulse_Time_3_Tmp
  3006. mov DShot_GCR_Pulse_Time_3, A
  3007. mov DShot_GCR_Start_Delay, #DSHOT_TLM_START_DELAY_48
  3008. ENDIF
  3009. jnb Flag_PGM_BIDIR, init_start_bidir_done ; Check if bidirectional operation
  3010. clr Flag_PGM_DIR_REV ; Set spinning direction. Default fwd
  3011. jnb Flag_RCP_DIR_REV, ($+5) ; Check force direction
  3012. setb Flag_PGM_DIR_REV ; Set spinning direction
  3013. init_start_bidir_done:
  3014. setb Flag_STARTUP_PHASE ; Set startup phase flag
  3015. mov Startup_Cnt, #0 ; Reset counter
  3016. call comm5comm6 ; Initialize commutation
  3017. call comm6comm1
  3018. call initialize_timing ; Initialize timing
  3019. call calc_next_comm_timing ; Set virtual commutation point
  3020. call initialize_timing ; Initialize timing
  3021. call calc_next_comm_timing
  3022. call initialize_timing ; Initialize timing
  3023. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  3024. ;
  3025. ; Run entry point
  3026. ;
  3027. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  3028. ; Run 1 = B(p-on) + C(n-pwm) - comparator A evaluated
  3029. ; Out_cA changes from low to high
  3030. run1:
  3031. call wait_for_comp_out_high ; Wait for high
  3032. ; setup_comm_wait ; Setup wait time from zero cross to commutation
  3033. ; evaluate_comparator_integrity ; Check whether comparator reading has been normal
  3034. call wait_for_comm ; Wait from zero cross to commutation
  3035. call comm1comm2 ; Commutate
  3036. call calc_next_comm_timing ; Calculate next timing and wait advance timing wait
  3037. ; wait_advance_timing ; Wait advance timing and start zero cross wait
  3038. ; calc_new_wait_times
  3039. ; wait_before_zc_scan ; Wait zero cross wait and start zero cross timeout
  3040. ; Run 2 = A(p-on) + C(n-pwm) - comparator B evaluated
  3041. ; Out_cB changes from high to low
  3042. run2:
  3043. call wait_for_comp_out_low
  3044. ; setup_comm_wait
  3045. ; evaluate_comparator_integrity
  3046. call set_pwm_limit ; Set pwm power limit for low or high rpm
  3047. call wait_for_comm
  3048. call comm2comm3
  3049. call calc_next_comm_timing
  3050. ; wait_advance_timing
  3051. ; calc_new_wait_times
  3052. ; wait_before_zc_scan
  3053. ; Run 3 = A(p-on) + B(n-pwm) - comparator C evaluated
  3054. ; Out_cC changes from low to high
  3055. run3:
  3056. call wait_for_comp_out_high
  3057. ; setup_comm_wait
  3058. ; evaluate_comparator_integrity
  3059. call wait_for_comm
  3060. call comm3comm4
  3061. call calc_next_comm_timing
  3062. ; wait_advance_timing
  3063. ; calc_new_wait_times
  3064. ; wait_before_zc_scan
  3065. ; Run 4 = C(p-on) + B(n-pwm) - comparator A evaluated
  3066. ; Out_cA changes from high to low
  3067. run4:
  3068. call wait_for_comp_out_low
  3069. ; setup_comm_wait
  3070. ; evaluate_comparator_integrity
  3071. call wait_for_comm
  3072. call comm4comm5
  3073. call calc_next_comm_timing
  3074. ; wait_advance_timing
  3075. ; calc_new_wait_times
  3076. ; wait_before_zc_scan
  3077. ; Run 5 = C(p-on) + A(n-pwm) - comparator B evaluated
  3078. ; Out_cB changes from low to high
  3079. run5:
  3080. call wait_for_comp_out_high
  3081. ; setup_comm_wait
  3082. ; evaluate_comparator_integrity
  3083. call wait_for_comm
  3084. call comm5comm6
  3085. call calc_next_comm_timing
  3086. ; wait_advance_timing
  3087. ; calc_new_wait_times
  3088. ; wait_before_zc_scan
  3089. ; Run 6 = B(p-on) + A(n-pwm) - comparator C evaluated
  3090. ; Out_cC changes from high to low
  3091. run6:
  3092. Start_Adc ; Start adc conversion
  3093. call wait_for_comp_out_low
  3094. ; setup_comm_wait
  3095. ; evaluate_comparator_integrity
  3096. call wait_for_comm
  3097. call comm6comm1
  3098. call check_temp_voltage_and_limit_power
  3099. call calc_next_comm_timing
  3100. ; wait_advance_timing
  3101. ; calc_new_wait_times
  3102. ; wait_before_zc_scan
  3103. ; Check if it is direct startup
  3104. jnb Flag_STARTUP_PHASE, normal_run_checks
  3105. ; Set spoolup power variables
  3106. mov Pwm_Limit, Pwm_Limit_Beg ; Set initial max power
  3107. ; Check startup counter
  3108. mov Temp2, #24 ; Set nominal startup parameters
  3109. mov Temp3, #12
  3110. clr C
  3111. mov A, Startup_Cnt ; Load counter
  3112. subb A, Temp2 ; Is counter above requirement?
  3113. jc direct_start_check_rcp ; No - proceed
  3114. clr Flag_STARTUP_PHASE ; Clear startup phase flag
  3115. setb Flag_INITIAL_RUN_PHASE ; Set initial run phase flag
  3116. mov Initial_Run_Rot_Cntd, Temp3 ; Set initial run rotation count
  3117. mov Pwm_Limit, Pwm_Limit_Beg
  3118. mov Pwm_Limit_By_Rpm, Pwm_Limit_Beg
  3119. sjmp normal_run_checks
  3120. direct_start_check_rcp:
  3121. jnb Flag_RCP_STOP, run1 ; If pulse is above stop value - Continue to run
  3122. ajmp run_to_wait_for_power_on
  3123. normal_run_checks:
  3124. ; Check if it is initial run phase
  3125. jnb Flag_INITIAL_RUN_PHASE, initial_run_phase_done ; If not initial run phase - branch
  3126. jb Flag_DIR_CHANGE_BRAKE, initial_run_phase_done ; If a direction change - branch
  3127. ; Decrement startup rotaton count
  3128. mov A, Initial_Run_Rot_Cntd
  3129. dec A
  3130. ; Check number of initial rotations
  3131. jnz initial_run_check_startup_rot ; Branch if counter is not zero
  3132. clr Flag_INITIAL_RUN_PHASE ; Clear initial run phase flag
  3133. setb Flag_MOTOR_STARTED ; Set motor started
  3134. ajmp run1 ; Continue with normal run
  3135. initial_run_check_startup_rot:
  3136. mov Initial_Run_Rot_Cntd, A ; Not zero - store counter
  3137. jb Flag_PGM_BIDIR, initial_run_continue_run ; Check if bidirectional operation
  3138. jb Flag_RCP_STOP, run_to_wait_for_power_on ; Check if pulse is below stop value
  3139. initial_run_continue_run:
  3140. ajmp run1 ; Continue to run
  3141. initial_run_phase_done:
  3142. ; Reset stall count
  3143. mov Stall_Cnt, #0
  3144. ; Exit run loop after a given time
  3145. jb Flag_PGM_BIDIR, run6_check_timeout ; Check if bidirectional operation
  3146. mov Temp1, #250
  3147. mov Temp2, #Pgm_Brake_On_Stop
  3148. mov A, @Temp2
  3149. jz ($+4)
  3150. mov Temp1, #3 ; About 100ms before stopping when brake is set
  3151. clr C
  3152. mov A, Rcp_Stop_Cnt ; Load stop RC pulse counter low byte value
  3153. subb A, Temp1 ; Is number of stop RC pulses above limit?
  3154. jnc run_to_wait_for_power_on ; Yes, go back to wait for poweron
  3155. run6_check_timeout:
  3156. mov A, Rcp_Timeout_Cntd ; Load RC pulse timeout counter value
  3157. jz run_to_wait_for_power_on ; If it is zero - go back to wait for poweron
  3158. run6_check_dir:
  3159. jnb Flag_PGM_BIDIR, run6_check_speed ; Check if bidirectional operation
  3160. jb Flag_PGM_DIR_REV, run6_check_dir_rev ; Check if actual rotation direction
  3161. jb Flag_RCP_DIR_REV, run6_check_dir_change ; Matches force direction
  3162. sjmp run6_check_speed
  3163. run6_check_dir_rev:
  3164. jnb Flag_RCP_DIR_REV, run6_check_dir_change
  3165. sjmp run6_check_speed
  3166. run6_check_dir_change:
  3167. jb Flag_DIR_CHANGE_BRAKE, run6_check_speed
  3168. setb Flag_DIR_CHANGE_BRAKE ; Set brake flag
  3169. mov Pwm_Limit, Pwm_Limit_Beg ; Set max power while braking
  3170. ajmp run4 ; Go back to run 4, thereby changing force direction
  3171. run6_check_speed:
  3172. mov Temp1, #0F0h ; Default minimum speed
  3173. jnb Flag_DIR_CHANGE_BRAKE, run6_brake_done; Is it a direction change?
  3174. mov Pwm_Limit, Pwm_Limit_Beg ; Set max power while braking
  3175. mov Temp1, #20h ; Bidirectional braking termination speed
  3176. run6_brake_done:
  3177. clr C
  3178. mov A, Comm_Period4x_H ; Is Comm_Period4x more than 32ms (~1220 eRPM)?
  3179. subb A, Temp1
  3180. jnc ($+5) ; Yes - stop or turn direction
  3181. ajmp run1 ; No - go back to run 1
  3182. jnb Flag_DIR_CHANGE_BRAKE, run_to_wait_for_power_on ; If it is not a direction change - stop
  3183. clr Flag_DIR_CHANGE_BRAKE ; Clear brake flag
  3184. clr Flag_PGM_DIR_REV ; Set spinning direction. Default fwd
  3185. jnb Flag_RCP_DIR_REV, ($+5) ; Check force direction
  3186. setb Flag_PGM_DIR_REV ; Set spinning direction
  3187. setb Flag_INITIAL_RUN_PHASE
  3188. mov Initial_Run_Rot_Cntd, #18
  3189. mov Pwm_Limit, Pwm_Limit_Beg ; Set initial max power
  3190. ajmp run1 ; Go back to run 1
  3191. run_to_wait_for_power_on_fail:
  3192. inc Stall_Cnt ; Increment stall count
  3193. ; Check if RCP is zero, then it is a normal stop
  3194. jnb Flag_RCP_STOP, run_to_wait_for_power_on_stall_done
  3195. run_to_wait_for_power_on:
  3196. mov Stall_Cnt, #0
  3197. run_to_wait_for_power_on_stall_done:
  3198. clr IE_EA
  3199. call switch_power_off
  3200. mov Flags0, #0 ; Clear flags0
  3201. mov Flags1, #0 ; Clear flags1
  3202. mov Flags_Startup, #0 ; Clear startup flags
  3203. IF MCU_48MHZ == 1
  3204. Set_MCU_Clk_24MHz
  3205. ; Scale DShot criteria for 24MHz
  3206. clr C
  3207. mov A, DShot_Frame_Length_Thr ; Scale frame length criteria
  3208. rrc A
  3209. mov DShot_Frame_Length_Thr, A
  3210. clr C
  3211. mov A, DShot_Pwm_Thr ; Scale pulse width criteria
  3212. rrc A
  3213. mov DShot_Pwm_Thr, A
  3214. ; Scale DShot telemetry for 24MHz
  3215. mov A, DShot_GCR_Pulse_Time_1
  3216. xch A, DShot_GCR_Pulse_Time_1_Tmp
  3217. mov DShot_GCR_Pulse_Time_1, A
  3218. mov A, DShot_GCR_Pulse_Time_2
  3219. xch A, DShot_GCR_Pulse_Time_2_Tmp
  3220. mov DShot_GCR_Pulse_Time_2, A
  3221. mov A, DShot_GCR_Pulse_Time_3
  3222. xch A, DShot_GCR_Pulse_Time_3_Tmp
  3223. mov DShot_GCR_Pulse_Time_3, A
  3224. mov DShot_GCR_Start_Delay, #DSHOT_TLM_START_DELAY
  3225. ENDIF
  3226. setb IE_EA
  3227. call wait100ms ; Wait for pwm to be stopped
  3228. call switch_power_off
  3229. mov Temp1, #Pgm_Brake_On_Stop
  3230. mov A, @Temp1
  3231. jz run_to_wait_for_power_on_brake_done
  3232. AcomFET_on
  3233. BcomFET_on
  3234. CcomFET_on
  3235. run_to_wait_for_power_on_brake_done:
  3236. clr C
  3237. mov A, Stall_Cnt
  3238. subb A, #10 ; Maximum consecutive stalls before stopping
  3239. jc ($+5)
  3240. ljmp init_no_signal ; Stalled too many times
  3241. ljmp wait_for_power_on ; Go back to wait for power on
  3242. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  3243. $include (BLHeliPgm.inc) ; Include source code for programming the ESC
  3244. $include (BLHeliBootLoad.inc) ; Include source code for bootloader
  3245. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  3246. CSEG AT 19FDh
  3247. reset:
  3248. ljmp pgm_start
  3249. END