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.

4518 lines
115 KiB

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