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.

4554 lines
116 KiB

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