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.

4233 lines
116 KiB

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