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.

3902 lines
101 KiB

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