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.

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