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.

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