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.

5324 lines
164 KiB

  1. ;**** **** **** **** ****
  2. ;
  3. ; BLHeli program for controlling brushless motors in helicopters and multirotors
  4. ;
  5. ; Copyright 2011, 2012 Steffen Skaug
  6. ; This program is distributed under the terms of the GNU General Public License
  7. ;
  8. ; This file is part of BLHeli.
  9. ;
  10. ; BLHeli is free software: you can redistribute it and/or modify
  11. ; it under the terms of the GNU General Public License as published by
  12. ; the Free Software Foundation, either version 3 of the License, or
  13. ; (at your option) any later version.
  14. ;
  15. ; BLHeli is distributed in the hope that it will be useful,
  16. ; but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. ; GNU General Public License for more details.
  19. ;
  20. ; You should have received a copy of the GNU General Public License
  21. ; along with BLHeli. If not, see <http://www.gnu.org/licenses/>.
  22. ;
  23. ;**** **** **** **** ****
  24. ;
  25. ; The software was initially designed for use with Eflite mCP X, but is now adapted to copters/planes in general
  26. ;
  27. ; The software was inspired by and started from from Bernard Konze's BLMC: http://home.versanet.de/~bkonze/blc_6a/blc_6a.htm
  28. ; And also Simon Kirby's TGY: https://github.com/sim-/tgy
  29. ;
  30. ; This file is best viewed with tab width set to 5
  31. ;
  32. ; The input signal can be positive 1kHz, 2kHz, 4kHz, 8kHz or 12kHz PWM (e.g. taken from the "resistor tap" on mCPx)
  33. ; And the input signal can be PPM (1-2ms) at rates up to several hundred Hz.
  34. ; The code adapts itself to the various input modes/frequencies
  35. ; The code ESC can also be programmed to accept inverted input signal.
  36. ;
  37. ; The first lines of the software must be modified according to the chosen environment:
  38. ; Uncomment the selected ESC and main/tail/multi mode
  39. ; BESC EQU "ESC"_"mode"
  40. ;
  41. ;**** **** **** **** ****
  42. ; Revision history:
  43. ; - Rev0.0: Initial revision
  44. ; - Rev1.0: Governor functionality added
  45. ; - Rev1.1: Increased tail gain to 1.0625. Implemented for tail only
  46. ; Decreased governor proportional and integral gain by 4
  47. ; Fixed bug that caused tail power not always to be max
  48. ; - Rev1.2: Governor integral gain should be higher in order to achieve full PWM range
  49. ; Integral gain can be higher, and is increased by 2x. An integral of +-128 can now be added to requested PWM
  50. ; - Rev1.3: Governor integral extended to 24bit
  51. ; Governor proportional gain increased by 2x
  52. ; Added slow spoolup/down for governor
  53. ; Set pwm to 100% (do not turn off nFET) for high values of current pwm
  54. ; Added support for PPM input (1us to 2us pulse)
  55. ; Removed USE_COMP_STORED as it was never used
  56. ; - Rev2.0 Added measurement of pwm frequency and support for 1kHz, 2kHz, 4kHz and 8kHz
  57. ; Optimized pwm on and off routines
  58. ; Improved mosfet switching in beep routines, to reduce current draw
  59. ; Added support for ICP1 interrupt pin input
  60. ; Added ADC measurement of supply voltage, with limiting of main motor power for low voltage
  61. ; Miscellaneous other changes
  62. ; - Rev2.1 Rewritten INT0 routine to be similar to ICP
  63. ; Reduced validation threshold (RCP_VALIDATE)
  64. ; Removed requirement for RCP to go to zero again in tail arming sequence
  65. ; Removed PPM support
  66. ; - Rev2.2 Added support for HC 5A 1S ESC with Atmega48V MPU
  67. ; Increased governor proportional gain by 2x
  68. ; - Rev3.0 Added functionality for programming from TX
  69. ; Added low voltage limit scaling for 2S and 3S
  70. ; - Rev11.2 Copied over from the SiLabs version and adapted to Atmel
  71. ; Now requiring a 16MHz capable MCU for fullspec performance
  72. ;
  73. ;
  74. ;**** **** **** **** ****
  75. ; 8K Bytes of In-System Self-Programmable Flash
  76. ; 1K Bytes Internal SRAM
  77. ; 512 Bytes Internal EEPROM
  78. ; 16MHz clock
  79. ;
  80. ;**** **** **** **** ****
  81. ; Timer 0 (500ns counts) always counts up and is used for
  82. ; - RC pulse timeout and skip counts
  83. ; Timer 1 (500ns counts) always counts up and is used for
  84. ; - RC pulse measurement (via external interrupt 0 or input capture pin)
  85. ; - Commutation timing (via output compare register A interrupt)
  86. ; Timer 2 (500ns counts) always counts up and is used for
  87. ; - PWM generation
  88. ;
  89. ;**** **** **** **** ****
  90. ; Interrupt handling
  91. ; The Atmega8 disables all interrupts when entering an interrupt routine,
  92. ; The code reenables interrupts in some interrupt routines, in order to nest pwm interrupts
  93. ; - Interrupts are disabled during beeps, to avoid audible interference from interrupts
  94. ; - RC pulse interrupts are periodically disabled in order to reduce interference with pwm interrupts.
  95. ;
  96. ;**** **** **** **** ****
  97. ; Motor control:
  98. ; - Brushless motor control with 6 states for each electrical 360 degrees
  99. ; - An advance timing of 0deg has zero cross 30deg after one commutation and 30deg before the next
  100. ; - Timing advance in this implementation is set to 15deg nominally
  101. ; - "Damped" commutation schemes are available, where more than one pfet is on when pwm is off. This will absorb energy from bemf and make step settling more damped.
  102. ; Motor sequence starting from zero crossing:
  103. ; - Timer wait: Wt_Comm 15deg ; Time to wait from zero cross to actual commutation
  104. ; - Timer wait: Wt_Advance 15deg ; Time to wait for timing advance. Nominal commutation point is after this
  105. ; - Timer wait: Wt_Zc_Scan 7.5deg ; Time to wait before looking for zero cross
  106. ; - Scan for zero cross 22.5deg , Nominal, with some motor variations
  107. ;
  108. ; Motor startup:
  109. ; Startup is the only phase, before normal bemf commutation run begins.
  110. ;
  111. ;**** **** **** **** ****
  112. ; Select the ESC and mode to use (or unselect all for use with external batch compile file);
  113. ;#define BLUESERIES_20A_MAIN
  114. ;#define BLUESERIES_20A_TAIL
  115. ;#define BLUESERIES_20A_MULTI
  116. ;#define BLUESERIES_30A_MAIN
  117. ;#define BLUESERIES_30A_TAIL
  118. ;#define BLUESERIES_30A_MULTI
  119. ;#define BLUESERIES_40A_MAIN
  120. ;#define BLUESERIES_40A_TAIL
  121. ;#define BLUESERIES_40A_MULTI
  122. ;#define HK_UBEC_20A_MAIN
  123. ;#define HK_UBEC_20A_TAIL
  124. ;#define HK_UBEC_20A_MULTI
  125. ;#define HK_UBEC_30A_MAIN
  126. ;#define HK_UBEC_30A_TAIL
  127. ;#define HK_UBEC_30A_MULTI
  128. ;#define HK_UBEC_40A_MAIN
  129. ;#define HK_UBEC_40A_TAIL
  130. ;#define HK_UBEC_40A_MULTI
  131. ;#define SUPERSIMPLE_18A_MAIN
  132. ;#define SUPERSIMPLE_18A_TAIL
  133. ;#define SUPERSIMPLE_18A_MULTI
  134. ;#define SUPERSIMPLE_20A_MAIN
  135. ;#define SUPERSIMPLE_20A_TAIL
  136. ;#define SUPERSIMPLE_20A_MULTI
  137. ;#define SUPERSIMPLE_30A_MAIN
  138. ;#define SUPERSIMPLE_30A_TAIL
  139. ;#define SUPERSIMPLE_30A_MULTI
  140. ;#define SUPERSIMPLE_40A_MAIN
  141. ;#define SUPERSIMPLE_40A_TAIL
  142. ;#define SUPERSIMPLE_40A_MULTI
  143. ;#define MULTISTAR_15A_MAIN ; Inverted input
  144. ;#define MULTISTAR_15A_TAIL
  145. ;#define MULTISTAR_15A_MULTI
  146. ;#define MULTISTAR_20A_MAIN ; Inverted input
  147. ;#define MULTISTAR_20A_TAIL
  148. ;#define MULTISTAR_20A_MULTI
  149. ;#define MULTISTAR_30A_MAIN ; Inverted input
  150. ;#define MULTISTAR_30A_TAIL
  151. ;#define MULTISTAR_30A_MULTI
  152. ;#define MULTISTAR_45A_MAIN ; Inverted input
  153. ;#define MULTISTAR_45A_TAIL
  154. ;#define MULTISTAR_45A_MULTI
  155. ;#define MYSTERY_30A_MAIN
  156. ;#define MYSTERY_30A_TAIL
  157. ;#define MYSTERY_30A_MULTI
  158. ;#define SUNRISE_HIMULTI_20A_MAIN ; Inverted input
  159. ;#define SUNRISE_HIMULTI_20A_TAIL
  160. ;#define SUNRISE_HIMULTI_20A_MULTI
  161. ;#define SUNRISE_HIMULTI_30A_MAIN ; Inverted input
  162. ;#define SUNRISE_HIMULTI_30A_TAIL
  163. ;#define SUNRISE_HIMULTI_30A_MULTI
  164. ;#define SUNRISE_HIMULTI_40A_MAIN ; Inverted input
  165. ;#define SUNRISE_HIMULTI_40A_TAIL
  166. ;#define SUNRISE_HIMULTI_40A_MULTI
  167. ;**** **** **** **** ****
  168. ; ESC selection statements
  169. #if defined(BLUESERIES_20A_MAIN)
  170. .EQU MODE = 0 ; Choose mode. Set to 0 for main motor
  171. .INCLUDE "BlueSeries_20A.inc" ; Select BlueSeries 20A pinout
  172. #endif
  173. #if defined(BLUESERIES_20A_TAIL)
  174. .EQU MODE = 1 ; Choose mode. Set to 1 for tail motor
  175. .INCLUDE "BlueSeries_20A.inc" ; Select BlueSeries 20A pinout
  176. #endif
  177. #if defined(BLUESERIES_20A_MULTI)
  178. .EQU MODE = 2 ; Choose mode. Set to 2 for multirotor
  179. .INCLUDE "BlueSeries_20A.inc" ; Select BlueSeries 20A pinout
  180. #endif
  181. #if defined(BLUESERIES_30A_MAIN)
  182. .EQU MODE = 0 ; Choose mode. Set to 0 for main motor
  183. .INCLUDE "BlueSeries_30A.inc" ; Select BlueSeries 30A pinout
  184. #endif
  185. #if defined(BLUESERIES_30A_TAIL)
  186. .EQU MODE = 1 ; Choose mode. Set to 1 for tail motor
  187. .INCLUDE "BlueSeries_30A.inc" ; Select BlueSeries 30A pinout
  188. #endif
  189. #if defined(BLUESERIES_30A_MULTI)
  190. .EQU MODE = 2 ; Choose mode. Set to 2 for multirotor
  191. .INCLUDE "BlueSeries_30A.inc" ; Select BlueSeries 30A pinout
  192. #endif
  193. #if defined(BLUESERIES_40A_MAIN)
  194. .EQU MODE = 0 ; Choose mode. Set to 0 for main motor
  195. .INCLUDE "BlueSeries_40A.inc" ; Select BlueSeries 40A pinout
  196. #endif
  197. #if defined(BLUESERIES_40A_TAIL)
  198. .EQU MODE = 1 ; Choose mode. Set to 1 for tail motor
  199. .INCLUDE "BlueSeries_40A.inc" ; Select BlueSeries 40A pinout
  200. #endif
  201. #if defined(BLUESERIES_40A_MULTI)
  202. .EQU MODE = 2 ; Choose mode. Set to 2 for multirotor
  203. .INCLUDE "BlueSeries_40A.inc" ; Select BlueSeries 40A pinout
  204. #endif
  205. #if defined(HK_UBEC_20A_MAIN)
  206. .EQU MODE = 0 ; Choose mode. Set to 0 for main motor
  207. .INCLUDE "HK_UBEC_20A.inc" ; Select Hobbyking UBEC 20A pinout
  208. #endif
  209. #if defined(HK_UBEC_20A_TAIL)
  210. .EQU MODE = 1 ; Choose mode. Set to 1 for tail motor
  211. .INCLUDE "HK_UBEC_20A.inc" ; Select Hobbyking UBEC 20A pinout
  212. #endif
  213. #if defined(HK_UBEC_20A_MULTI)
  214. .EQU MODE = 2 ; Choose mode. Set to 2 for multirotor
  215. .INCLUDE "HK_UBEC_20A.inc" ; Select Hobbyking UBEC 20A pinout
  216. #endif
  217. #if defined(HK_UBEC_30A_MAIN)
  218. .EQU MODE = 0 ; Choose mode. Set to 0 for main motor
  219. .INCLUDE "HK_UBEC_30A.inc" ; Select Hobbyking UBEC 30A pinout
  220. #endif
  221. #if defined(HK_UBEC_30A_TAIL)
  222. .EQU MODE = 1 ; Choose mode. Set to 1 for tail motor
  223. .INCLUDE "HK_UBEC_30A.inc" ; Select Hobbyking UBEC 30A pinout
  224. #endif
  225. #if defined(HK_UBEC_30A_MULTI)
  226. .EQU MODE = 2 ; Choose mode. Set to 2 for multirotor
  227. .INCLUDE "HK_UBEC_30A.inc" ; Select Hobbyking UBEC 30A pinout
  228. #endif
  229. #if defined(HK_UBEC_40A_MAIN)
  230. .EQU MODE = 0 ; Choose mode. Set to 0 for main motor
  231. .INCLUDE "HK_UBEC_40A.inc" ; Select Hobbyking UBEC 40A pinout
  232. #endif
  233. #if defined(HK_UBEC_40A_TAIL)
  234. .EQU MODE = 1 ; Choose mode. Set to 1 for tail motor
  235. .INCLUDE "HK_UBEC_40A.inc" ; Select Hobbyking UBEC 40A pinout
  236. #endif
  237. #if defined(HK_UBEC_40A_MULTI)
  238. .EQU MODE = 2 ; Choose mode. Set to 2 for multirotor
  239. .INCLUDE "HK_UBEC_40A.inc" ; Select Hobbyking UBEC 40A pinout
  240. #endif
  241. #if defined(SUPERSIMPLE_18A_MAIN)
  242. .EQU MODE = 0 ; Choose mode. Set to 0 for main motor
  243. .INCLUDE "SuperSimple_18A.inc" ; Select SuperSimple 18A pinout
  244. #endif
  245. #if defined(SUPERSIMPLE_18A_TAIL)
  246. .EQU MODE = 1 ; Choose mode. Set to 1 for tail motor
  247. .INCLUDE "SuperSimple_18A.inc" ; Select SuperSimple 18A pinout
  248. #endif
  249. #if defined(SUPERSIMPLE_18A_MULTI)
  250. .EQU MODE = 2 ; Choose mode. Set to 2 for multirotor
  251. .INCLUDE "SuperSimple_18A.inc" ; Select SuperSimple 18A pinout
  252. #endif
  253. #if defined(SUPERSIMPLE_20A_MAIN)
  254. .EQU MODE = 0 ; Choose mode. Set to 0 for main motor
  255. .INCLUDE "SuperSimple_20A.inc" ; Select SuperSimple 20A pinout
  256. #endif
  257. #if defined(SUPERSIMPLE_20A_TAIL)
  258. .EQU MODE = 1 ; Choose mode. Set to 1 for tail motor
  259. .INCLUDE "SuperSimple_20A.inc" ; Select SuperSimple 20A pinout
  260. #endif
  261. #if defined(SUPERSIMPLE_20A_MULTI)
  262. .EQU MODE = 2 ; Choose mode. Set to 2 for multirotor
  263. .INCLUDE "SuperSimple_20A.inc" ; Select SuperSimple 20A pinout
  264. #endif
  265. #if defined(SUPERSIMPLE_30A_MAIN)
  266. .EQU MODE = 0 ; Choose mode. Set to 0 for main motor
  267. .INCLUDE "SuperSimple_30A.inc" ; Select SuperSimple 30A pinout
  268. #endif
  269. #if defined(SUPERSIMPLE_30A_TAIL)
  270. .EQU MODE = 1 ; Choose mode. Set to 1 for tail motor
  271. .INCLUDE "SuperSimple_30A.inc" ; Select SuperSimple 30A pinout
  272. #endif
  273. #if defined(SUPERSIMPLE_30A_MULTI)
  274. .EQU MODE = 2 ; Choose mode. Set to 2 for multirotor
  275. .INCLUDE "SuperSimple_30A.inc" ; Select SuperSimple 30A pinout
  276. #endif
  277. #if defined(SUPERSIMPLE_40A_MAIN)
  278. .EQU MODE = 0 ; Choose mode. Set to 0 for main motor
  279. .INCLUDE "SuperSimple_40A.inc" ; Select SuperSimple 40A pinout
  280. #endif
  281. #if defined(SUPERSIMPLE_40A_TAIL)
  282. .EQU MODE = 1 ; Choose mode. Set to 1 for tail motor
  283. .INCLUDE "SuperSimple_40A.inc" ; Select SuperSimple 40A pinout
  284. #endif
  285. #if defined(SUPERSIMPLE_40A_MULTI)
  286. .EQU MODE = 2 ; Choose mode. Set to 2 for multirotor
  287. .INCLUDE "SuperSimple_40A.inc" ; Select SuperSimple 40A pinout
  288. #endif
  289. #if defined(MULTISTAR_15A_MAIN)
  290. .EQU MODE = 0 ; Choose mode. Set to 0 for main motor
  291. .INCLUDE "Multistar_15A.inc" ; Select Multistar 15A pinout
  292. #endif
  293. #if defined(MULTISTAR_15A_TAIL)
  294. .EQU MODE = 1 ; Choose mode. Set to 1 for tail motor
  295. .INCLUDE "Multistar_15A.inc" ; Select Multistar 15A pinout
  296. #endif
  297. #if defined(MULTISTAR_15A_MULTI)
  298. .EQU MODE = 2 ; Choose mode. Set to 2 for multirotor
  299. .INCLUDE "Multistar_15A.inc" ; Select Multistar 15A pinout
  300. #endif
  301. #if defined(MULTISTAR_20A_MAIN)
  302. .EQU MODE = 0 ; Choose mode. Set to 0 for main motor
  303. .INCLUDE "Multistar_20A.inc" ; Select Multistar 20A pinout
  304. #endif
  305. #if defined(MULTISTAR_20A_TAIL)
  306. .EQU MODE = 1 ; Choose mode. Set to 1 for tail motor
  307. .INCLUDE "Multistar_20A.inc" ; Select Multistar 20A pinout
  308. #endif
  309. #if defined(MULTISTAR_20A_MULTI)
  310. .EQU MODE = 2 ; Choose mode. Set to 2 for multirotor
  311. .INCLUDE "Multistar_20A.inc" ; Select Multistar 20A pinout
  312. #endif
  313. #if defined(MULTISTAR_30A_MAIN)
  314. .EQU MODE = 0 ; Choose mode. Set to 0 for main motor
  315. .INCLUDE "Multistar_30A.inc" ; Select Multistar 30A pinout
  316. #endif
  317. #if defined(MULTISTAR_30A_TAIL)
  318. .EQU MODE = 1 ; Choose mode. Set to 1 for tail motor
  319. .INCLUDE "Multistar_30A.inc" ; Select Multistar 30A pinout
  320. #endif
  321. #if defined(MULTISTAR_30A_MULTI)
  322. .EQU MODE = 2 ; Choose mode. Set to 2 for multirotor
  323. .INCLUDE "Multistar_30A.inc" ; Select Multistar 30A pinout
  324. #endif
  325. #if defined(MULTISTAR_45A_MAIN)
  326. .EQU MODE = 0 ; Choose mode. Set to 0 for main motor
  327. .INCLUDE "Multistar_45A.inc" ; Select Multistar 45A pinout
  328. #endif
  329. #if defined(MULTISTAR_45A_TAIL)
  330. .EQU MODE = 1 ; Choose mode. Set to 1 for tail motor
  331. .INCLUDE "Multistar_45A.inc" ; Select Multistar 45A pinout
  332. #endif
  333. #if defined(MULTISTAR_45A_MULTI)
  334. .EQU MODE = 2 ; Choose mode. Set to 2 for multirotor
  335. .INCLUDE "Multistar_45A.inc" ; Select Multistar 45A pinout
  336. #endif
  337. #if defined(MYSTERY_30A_MAIN)
  338. .EQU MODE = 0 ; Choose mode. Set to 0 for main motor
  339. .INCLUDE "Mystery_30A.inc" ; Select Mystery 30A pinout
  340. #endif
  341. #if defined(MYSTERY_30A_TAIL)
  342. .EQU MODE = 1 ; Choose mode. Set to 1 for tail motor
  343. .INCLUDE "Mystery_30A.inc" ; Select Mystery 30A pinout
  344. #endif
  345. #if defined(MYSTERY_30A_MULTI)
  346. .EQU MODE = 2 ; Choose mode. Set to 2 for multirotor
  347. .INCLUDE "Mystery_30A.inc" ; Select Mystery 30A pinout
  348. #endif
  349. #if defined(SUNRISE_HIMULTI_20A_MAIN)
  350. .EQU MODE = 0 ; Choose mode. Set to 0 for main motor
  351. .INCLUDE "Sunrise_HiMulti_20A.inc" ; Select Sunrise HiMulti 20A pinout
  352. #endif
  353. #if defined(SUNRISE_HIMULTI_20A_TAIL)
  354. .EQU MODE = 1 ; Choose mode. Set to 1 for tail motor
  355. .INCLUDE "Sunrise_HiMulti_20A.inc" ; Select Sunrise HiMulti 20A pinout
  356. #endif
  357. #if defined(SUNRISE_HIMULTI_20A_MULTI)
  358. .EQU MODE = 2 ; Choose mode. Set to 2 for multirotor
  359. .INCLUDE "Sunrise_HiMulti_20A.inc" ; Select Sunrise HiMulti 20A pinout
  360. #endif
  361. #if defined(SUNRISE_HIMULTI_30A_MAIN)
  362. .EQU MODE = 0 ; Choose mode. Set to 0 for main motor
  363. .INCLUDE "Sunrise_HiMulti_30A.inc" ; Select Sunrise HiMulti 30A pinout
  364. #endif
  365. #if defined(SUNRISE_HIMULTI_30A_TAIL)
  366. .EQU MODE = 1 ; Choose mode. Set to 1 for tail motor
  367. .INCLUDE "Sunrise_HiMulti_30A.inc" ; Select Sunrise HiMulti 30A pinout
  368. #endif
  369. #if defined(SUNRISE_HIMULTI_30A_MULTI)
  370. .EQU MODE = 2 ; Choose mode. Set to 2 for multirotor
  371. .INCLUDE "Sunrise_HiMulti_30A.inc" ; Select Sunrise HiMulti 30A pinout
  372. #endif
  373. #if defined(SUNRISE_HIMULTI_40A_MAIN)
  374. .EQU MODE = 0 ; Choose mode. Set to 0 for main motor
  375. .INCLUDE "Sunrise_HiMulti_40A.inc" ; Select Sunrise HiMulti 40A pinout
  376. #endif
  377. #if defined(SUNRISE_HIMULTI_40A_TAIL)
  378. .EQU MODE = 1 ; Choose mode. Set to 1 for tail motor
  379. .INCLUDE "Sunrise_HiMulti_40A.inc" ; Select Sunrise HiMulti 40A pinout
  380. #endif
  381. #if defined(SUNRISE_HIMULTI_40A_MULTI)
  382. .EQU MODE = 2 ; Choose mode. Set to 2 for multirotor
  383. .INCLUDE "Sunrise_HiMulti_40A.inc" ; Select Sunrise HiMulti 40A pinout
  384. #endif
  385. ;**** **** **** **** ****
  386. ; TX programming defaults
  387. ;
  388. ; Parameter dependencies:
  389. ; - Governor P gain, I gain and Range is only used if one of the three governor modes is selected
  390. ; - Governor setup target is only used if Setup governor mode is selected (or closed loop mode is on for multi)
  391. ; - Startup rpm and startup accel is only used if stepped startup method is selected
  392. ; - Damping force is only used if DampedLight or Damped is selected
  393. ;
  394. ; Main
  395. .EQU DEFAULT_PGM_MAIN_P_GAIN = 7 ; 1=0.13 2=0.17 3=0.25 4=0.38 5=0.50 6=0.75 7=1.00 8=1.5 9=2.0 10=3.0 11=4.0 12=6.0 13=8.0
  396. .EQU DEFAULT_PGM_MAIN_I_GAIN = 7 ; 1=0.13 2=0.17 3=0.25 4=0.38 5=0.50 6=0.75 7=1.00 8=1.5 9=2.0 10=3.0 11=4.0 12=6.0 13=8.0
  397. .EQU DEFAULT_PGM_MAIN_GOVERNOR_MODE = 1 ; 1=Tx 2=Arm 3=Setup 4=Off
  398. .EQU DEFAULT_PGM_MAIN_GOVERNOR_RANGE = 1 ; 1=High 2=Middle 3=Low
  399. .EQU DEFAULT_PGM_MAIN_LOW_VOLTAGE_LIM = 4 ; 1=Off 2=3.0V/c 3=3.1V/c 4=3.2V/c 5=3.3V/c 6=3.4V/c
  400. .EQU DEFAULT_PGM_MAIN_COMM_TIMING = 3 ; 1=Low 2=MediumLow 3=Medium 4=MediumHigh 5=High
  401. .EQU DEFAULT_PGM_MAIN_THROTTLE_RATE = 13 ; 1=2 2=3 3=4 4=6 5=8 6=12 7=16 8=24 9=32 10=48 11=64 12=128 13=255
  402. .EQU DEFAULT_PGM_MAIN_DAMPING_FORCE = 1 ; 1=VeryLow 2=Low 3=MediumLow 4=MediumHigh 5=High 6=Highest
  403. .EQU DEFAULT_PGM_MAIN_PWM_FREQ = 2 ; 1=High 2=Low 3=DampedLight
  404. .EQU DEFAULT_PGM_MAIN_DEMAG_COMP = 1 ; 1=Disabled 2=Low 3=High
  405. .EQU DEFAULT_PGM_MAIN_DIRECTION = 1 ; 1=Normal 2=Reversed
  406. .EQU DEFAULT_PGM_MAIN_RCP_PWM_POL = 1 ; 1=Positive 2=Negative
  407. .EQU DEFAULT_PGM_MAIN_GOV_SETUP_TARGET = 180; Target for governor in setup mode. Corresponds to 70% throttle
  408. .EQU DEFAULT_PGM_MAIN_REARM_START = 0 ; 1=Enabled 0=Disabled
  409. .EQU DEFAULT_PGM_MAIN_BEEP_STRENGTH = 120; Beep strength
  410. .EQU DEFAULT_PGM_MAIN_BEACON_STRENGTH = 200; Beacon strength
  411. .EQU DEFAULT_PGM_MAIN_BEACON_DELAY = 4 ; 1=1m 2=2m 3=5m 4=10m 5=Infinite
  412. ; Tail
  413. .EQU DEFAULT_PGM_TAIL_GAIN = 3 ; 1=0.75 2=0.88 3=1.00 4=1.12 5=1.25
  414. .EQU DEFAULT_PGM_TAIL_IDLE_SPEED = 4 ; 1=Low 2=MediumLow 3=Medium 4=MediumHigh 5=High
  415. .EQU DEFAULT_PGM_TAIL_COMM_TIMING = 3 ; 1=Low 2=MediumLow 3=Medium 4=MediumHigh 5=High
  416. .EQU DEFAULT_PGM_TAIL_THROTTLE_RATE = 13 ; 1=2 2=3 3=4 4=6 5=8 6=12 7=16 8=24 9=32 10=48 11=64 12=128 13=255
  417. .EQU DEFAULT_PGM_TAIL_DAMPING_FORCE = 5 ; 1=VeryLow 2=Low 3=MediumLow 4=MediumHigh 5=High 6=Highest
  418. .IF DAMPED_MODE_ENABLE == 1
  419. .EQU DEFAULT_PGM_TAIL_PWM_FREQ = 4 ; 1=High 2=Low 3=DampedLight 4=Damped
  420. .ELSE
  421. .EQU DEFAULT_PGM_TAIL_PWM_FREQ = 3 ; 1=High 2=Low 3=DampedLight
  422. .ENDIF
  423. .EQU DEFAULT_PGM_TAIL_DEMAG_COMP = 1 ; 1=Disabled 2=Low 3=High
  424. .EQU DEFAULT_PGM_TAIL_DIRECTION = 1 ; 1=Normal 2=Reversed 3=Bidirectional
  425. .EQU DEFAULT_PGM_TAIL_RCP_PWM_POL = 1 ; 1=Positive 2=Negative
  426. .EQU DEFAULT_PGM_TAIL_BEEP_STRENGTH = 250; Beep strength
  427. .EQU DEFAULT_PGM_TAIL_BEACON_STRENGTH = 250; Beacon strength
  428. .EQU DEFAULT_PGM_TAIL_BEACON_DELAY = 4 ; 1=1m 2=2m 3=5m 4=10m 5=Infinite
  429. ; Multi
  430. .EQU DEFAULT_PGM_MULTI_P_GAIN = 9 ; 1=0.13 2=0.17 3=0.25 4=0.38 5=0.50 6=0.75 7=1.00 8=1.5 9=2.0 10=3.0 11=4.0 12=6.0 13=8.0
  431. .EQU DEFAULT_PGM_MULTI_I_GAIN = 9 ; 1=0.13 2=0.17 3=0.25 4=0.38 5=0.50 6=0.75 7=1.00 8=1.5 9=2.0 10=3.0 11=4.0 12=6.0 13=8.0
  432. .EQU DEFAULT_PGM_MULTI_GOVERNOR_MODE = 4 ; 1=HiRange 2=MidRange 3=LoRange 4=Off
  433. .EQU DEFAULT_PGM_MULTI_GAIN = 3 ; 1=0.75 2=0.88 3=1.00 4=1.12 5=1.25
  434. .EQU DEFAULT_PGM_MULTI_LOW_VOLTAGE_LIM = 1 ; 1=Off 2=3.0V/c 3=3.1V/c 4=3.2V/c 5=3.3V/c 6=3.4V/c
  435. .EQU DEFAULT_PGM_MULTI_COMM_TIMING = 3 ; 1=Low 2=MediumLow 3=Medium 4=MediumHigh 5=High
  436. .EQU DEFAULT_PGM_MULTI_THROTTLE_RATE = 13 ; 1=2 2=3 3=4 4=6 5=8 6=12 7=16 8=24 9=32 10=48 11=64 12=128 13=255
  437. .EQU DEFAULT_PGM_MULTI_DAMPING_FORCE = 6 ; 1=VeryLow 2=Low 3=MediumLow 4=MediumHigh 5=High 6=Highest
  438. .IF DAMPED_MODE_ENABLE == 1
  439. .EQU DEFAULT_PGM_MULTI_PWM_FREQ = 1 ; 1=High 2=Low 3=DampedLight 4=Damped
  440. .ELSE
  441. .EQU DEFAULT_PGM_MULTI_PWM_FREQ = 1 ; 1=High 2=Low 3=DampedLight
  442. .ENDIF
  443. .EQU DEFAULT_PGM_MULTI_DEMAG_COMP = 2 ; 1=Disabled 2=Low 3=High
  444. .EQU DEFAULT_PGM_MULTI_DIRECTION = 1 ; 1=Normal 2=Reversed 3=Bidirectional
  445. .EQU DEFAULT_PGM_MULTI_RCP_PWM_POL = 1 ; 1=Positive 2=Negative
  446. .EQU DEFAULT_PGM_MULTI_BEEP_STRENGTH = 40 ; Beep strength
  447. .EQU DEFAULT_PGM_MULTI_BEACON_STRENGTH = 80 ; Beacon strength
  448. .EQU DEFAULT_PGM_MULTI_BEACON_DELAY = 4 ; 1=1m 2=2m 3=5m 4=10m 5=Infinite
  449. ; Common
  450. .EQU DEFAULT_PGM_ENABLE_TX_PROGRAM = 1 ; 1=Enabled 0=Disabled
  451. .EQU DEFAULT_PGM_PPM_MIN_THROTTLE = 37 ; 4*37+1000=1148
  452. .EQU DEFAULT_PGM_PPM_MAX_THROTTLE = 208; 4*208+1000=1832
  453. .EQU DEFAULT_PGM_PPM_CENTER_THROTTLE = 122; 4*122+1000=1488 (used in bidirectional mode)
  454. .EQU DEFAULT_PGM_BEC_VOLTAGE_HIGH = 0 ; 0=Low 1= High
  455. ;**** **** **** **** ****
  456. ; Constant definitions for main
  457. .IF MODE == 0
  458. .EQU GOV_SPOOLRATE = 2 ; Number of steps for governor requested pwm per 32ms
  459. .EQU RCP_TIMEOUT_PPM = 10 ; Number of timer2H overflows (about 32ms) before considering rc pulse lost
  460. .EQU RCP_TIMEOUT = 64 ; Number of timer2L overflows (about 128us) before considering rc pulse lost
  461. .EQU RCP_SKIP_RATE = 32 ; Number of timer2L overflows (about 128us) before reenabling rc pulse detection
  462. .EQU RCP_MIN = 0 ; This is minimum RC pulse length
  463. .EQU RCP_MAX = 255 ; This is maximum RC pulse length
  464. .EQU RCP_VALIDATE = 2 ; Require minimum this pulse length to validate RC pulse
  465. .EQU RCP_STOP = 1 ; Stop motor at or below this pulse length
  466. .EQU RCP_STOP_LIMIT = 250 ; Stop motor if this many timer2H overflows (~32ms) are below stop limit
  467. .EQU PWM_START = 50 ; PWM used as max power during start
  468. .EQU COMM_TIME_RED = 8 ; Fixed reduction (in us) for commutation wait (to account for fixed delays)
  469. .EQU COMM_TIME_MIN = 1 ; Minimum time (in us) for commutation wait
  470. .EQU TEMP_CHECK_RATE = 8 ; Number of adc conversions for each check of temperature (the other conversions are used for voltage)
  471. .ENDIF
  472. ; Constant definitions for tail
  473. .IF MODE == 1
  474. .EQU GOV_SPOOLRATE = 1 ; Number of steps for governor requested pwm per 32ms
  475. .EQU RCP_TIMEOUT_PPM = 10 ; Number of timer2H overflows (about 32ms) before considering rc pulse lost
  476. .EQU RCP_TIMEOUT = 24 ; Number of timer2L overflows (about 128us) before considering rc pulse lost
  477. .EQU RCP_SKIP_RATE = 6 ; Number of timer2L overflows (about 128us) before reenabling rc pulse detection
  478. .EQU RCP_MIN = 0 ; This is minimum RC pulse length
  479. .EQU RCP_MAX = 255 ; This is maximum RC pulse length
  480. .EQU RCP_VALIDATE = 2 ; Require minimum this pulse length to validate RC pulse
  481. .EQU RCP_STOP = 1 ; Stop motor at or below this pulse length
  482. .EQU RCP_STOP_LIMIT = 130 ; Stop motor if this many timer2H overflows (~32ms) are below stop limit
  483. .EQU PWM_START = 50 ; PWM used as max power during start
  484. .EQU COMM_TIME_RED = 8 ; Fixed reduction (in us) for commutation wait (to account for fixed delays)
  485. .EQU COMM_TIME_MIN = 1 ; Minimum time (in us) for commutation wait
  486. .EQU TEMP_CHECK_RATE = 8 ; Number of adc conversions for each check of temperature (the other conversions are used for voltage)
  487. .ENDIF
  488. ; Constant definitions for multi
  489. .IF MODE == 2
  490. .EQU GOV_SPOOLRATE = 1 ; Number of steps for governor requested pwm per 32ms
  491. .EQU RCP_TIMEOUT_PPM = 10 ; Number of timer2H overflows (about 32ms) before considering rc pulse lost
  492. .EQU RCP_TIMEOUT = 24 ; Number of timer2L overflows (about 128us) before considering rc pulse lost
  493. .EQU RCP_SKIP_RATE = 6 ; Number of timer2L overflows (about 128us) before reenabling rc pulse detection
  494. .EQU RCP_MIN = 0 ; This is minimum RC pulse length
  495. .EQU RCP_MAX = 255 ; This is maximum RC pulse length
  496. .EQU RCP_VALIDATE = 2 ; Require minimum this pulse length to validate RC pulse
  497. .EQU RCP_STOP = 1 ; Stop motor at or below this pulse length
  498. .EQU RCP_STOP_LIMIT = 250 ; Stop motor if this many timer2H overflows (~32ms) are below stop limit
  499. .EQU PWM_START = 50 ; PWM used as max power during start
  500. .EQU COMM_TIME_RED = 10 ; Fixed reduction (in us) for commutation wait (to account for fixed delays)
  501. .EQU COMM_TIME_MIN = 1 ; Minimum time (in us) for commutation wait
  502. .EQU TEMP_CHECK_RATE = 8 ; Number of adc conversions for each check of temperature (the other conversions are used for voltage)
  503. .ENDIF
  504. ;**** **** **** **** ****
  505. ; Register definitions
  506. .DEF Mul_Res_L = R0 ; Reserved for mul instruction
  507. .DEF Mul_Res_H = R1 ; Reserved for mul instruction
  508. .DEF Zero = R2 ; Register variable initialized to 0, always at 0
  509. .DEF I_Sreg = R3 ; Status register saved in interrupts
  510. .DEF II_Sreg = R4 ; Status register saved in nested interrupts (pwm interrupts from timer2)
  511. .DEF Current_Pwm_Limited = R5 ; Current_Pwm_Limited is allocated to a register for fast access
  512. .DEF Temp1 = R16 ; Main temporary
  513. .DEF Temp2 = R17 ; Main temporary (Temp1/2 must be two consecutive registers)
  514. .DEF Temp3 = R18 ; Main temporary
  515. .DEF Temp4 = R19 ; Main temporary
  516. .DEF Temp5 = R6 ; Main temporary (limited operations)
  517. .DEF Temp6 = R7 ; Main temporary (limited operations)
  518. .DEF Temp7 = R8 ; Main temporary (limited operations)
  519. .DEF Temp8 = R9 ; Main temporary (limited operations)
  520. .DEF I_Temp1 = R20 ; Interrupt temporary
  521. .DEF I_Temp2 = R21 ; Interrupt temporary
  522. .DEF I_Temp3 = R10 ; Interrupt temporary (limited operations)
  523. .DEF I_Temp4 = R11 ; Interrupt temporary (limited operations)
  524. .DEF I_Temp5 = R12 ; Interrupt temporary (limited operations)
  525. .DEF I_Temp6 = R13 ; Interrupt temporary (limited operations)
  526. .DEF I_Temp7 = R14 ; Interrupt temporary (limited operations)
  527. .DEF I_Temp8 = R15 ; Interrupt temporary (limited operations)
  528. .DEF Flags0 = R22 ; State flags. Reset upon init_start
  529. .EQU OC1A_PENDING = 0 ; Timer1 output compare pending flag
  530. .EQU RCP_MEAS_PWM_FREQ = 1 ; Measure RC pulse pwm frequency
  531. .EQU PWM_ON = 2 ; Set in on part of pwm cycle
  532. .EQU DEMAG_DETECTED = 3 ; Set when excessive demag time is detected
  533. .EQU DEMAG_CUT_POWER = 4 ; Set when demag compensation cuts power
  534. .EQU GOV_ACTIVE = 5 ; Set when governor is active
  535. ;.EQU = 6
  536. ;.EQU = 7
  537. .DEF Flags1 = R23 ; State flags. Reset upon init_start
  538. .EQU MOTOR_SPINNING = 0 ; Set when in motor is spinning
  539. .EQU STARTUP_PHASE = 1 ; Set when in startup phase
  540. .EQU INITIAL_RUN_PHASE = 2 ; Set when in initial run phase, before synchronized run is achieved
  541. .EQU CURR_PWMOFF_DAMPED = 3 ; Currently running pwm off cycle is damped
  542. .EQU CURR_PWMOFF_COMP_ABLE = 4 ; Currently running pwm off cycle is usable for comparator
  543. .EQU ADC_READ_TEMP = 5 ; Set when ADC input shall be set to read temperature
  544. ;.EQU = 6
  545. ;.EQU = 7
  546. .DEF Flags2 = R24 ; State flags. NOT reset upon init_start
  547. .EQU RCP_UPDATED = 0 ; New RC pulse length value available
  548. .EQU RCP_EDGE_NO = 1 ; RC pulse edge no. 0=rising, 1=falling
  549. .EQU PGM_PWMOFF_DAMPED = 2 ; Programmed pwm off damped mode. Set when fully damped or damped light mode is selected
  550. .EQU PGM_PWMOFF_DAMPED_FULL = 3 ; Programmed pwm off fully damped mode. Set when all pfets shall be on in pwm_off period
  551. .EQU PGM_PWMOFF_DAMPED_LIGHT = 4 ; Programmed pwm off damped light mode. Set when only 2 pfets shall be on in pwm_off period
  552. .EQU PGM_PWM_HIGH_FREQ = 5 ; Progremmed pwm high frequency
  553. .EQU RCP_INT_NESTED_ENABLED = 6 ; Set when RC pulse interrupt is enabled around nested interrupts
  554. ;.EQU = 7
  555. .DEF Flags3 = R25 ; State flags. NOT reset upon init_start
  556. .EQU RCP_PWM_FREQ_1KHZ = 0 ; RC pulse pwm frequency is 1kHz
  557. .EQU RCP_PWM_FREQ_2KHZ = 1 ; RC pulse pwm frequency is 2kHz
  558. .EQU RCP_PWM_FREQ_4KHZ = 2 ; RC pulse pwm frequency is 4kHz
  559. .EQU RCP_PWM_FREQ_8KHZ = 3 ; RC pulse pwm frequency is 8kHz
  560. .EQU RCP_PWM_FREQ_12KHZ = 4 ; RC pulse pwm frequency is 12kHz
  561. .EQU PGM_DIR_REV = 5 ; Programmed direction. 0=normal, 1=reversed
  562. .EQU PGM_RCP_PWM_POL = 6 ; Programmed RC pulse pwm polarity. 0=positive, 1=negative
  563. .EQU FULL_THROTTLE_RANGE = 7 ; When set full throttle range is used (1000-2000us) and stored calibration values are ignored
  564. ; Here the general temporary register XYZ are placed (R26-R31)
  565. ; XH: General temporary used by main routines
  566. ; XL: General temporary used by interrupt routines
  567. ; Y: General temporary used by timer2 pwm interrupt routine
  568. ; Z: Address of current PWM FET ON routine (eg: pwm_afet_on)
  569. ;**** **** **** **** ****
  570. ; RAM definitions
  571. .DSEG ; Data segment
  572. .ORG SRAM_START
  573. Timer0_Int_Cnt: .BYTE 1 ; Timer0 interrupt counter
  574. Requested_Pwm: .BYTE 1 ; Requested pwm (from RC pulse value)
  575. Governor_Req_Pwm: .BYTE 1 ; Governor requested pwm (sets governor target)
  576. Current_Pwm: .BYTE 1 ; Current pwm
  577. Rcp_Prev_Edge_L: .BYTE 1 ; RC pulse previous edge timer3 timestamp (lo byte)
  578. Rcp_Prev_Edge_H: .BYTE 1 ; RC pulse previous edge timer3 timestamp (hi byte)
  579. Rcp_Timeout_Cnt: .BYTE 1 ; RC pulse timeout counter (decrementing)
  580. Rcp_Skip_Cnt: .BYTE 1 ; RC pulse skip counter (decrementing)
  581. Rcp_Edge_Cnt: .BYTE 1 ; RC pulse edge counter
  582. Initial_Arm: .BYTE 1 ; Variable that is set during the first arm sequence after power on
  583. Power_On_Wait_Cnt_L: .BYTE 1 ; Power on wait counter (lo byte)
  584. Power_On_Wait_Cnt_H: .BYTE 1 ; Power on wait counter (hi byte)
  585. Startup_Rot_Cnt: .BYTE 1 ; Startup phase rotations counter
  586. Startup_Ok_Cnt: .BYTE 1 ; Startup phase ok comparator waits counter (incrementing)
  587. Demag_Consecutive_Cnt: .BYTE 1 ; Counter used to count consecutive demag events
  588. Prev_Comm_L: .BYTE 1 ; Previous commutation timer3 timestamp (lo byte)
  589. Prev_Comm_H: .BYTE 1 ; Previous commutation timer3 timestamp (hi byte)
  590. Comm_Period4x_L: .BYTE 1 ; Timer3 counts between the last 4 commutations (lo byte)
  591. Comm_Period4x_H: .BYTE 1 ; Timer3 counts between the last 4 commutations (hi byte)
  592. Comm_Phase: .BYTE 1 ; Current commutation phase
  593. Comp_Wait_Reads: .BYTE 1 ; Comparator wait comparator reads
  594. Gov_Target_L: .BYTE 1 ; Governor target (lo byte)
  595. Gov_Target_H: .BYTE 1 ; Governor target (hi byte)
  596. Gov_Integral_L: .BYTE 1 ; Governor integral error (lo byte)
  597. Gov_Integral_H: .BYTE 1 ; Governor integral error (hi byte)
  598. Gov_Integral_X: .BYTE 1 ; Governor integral error (ex byte)
  599. Gov_Proportional_L: .BYTE 1 ; Governor proportional error (lo byte)
  600. Gov_Proportional_H: .BYTE 1 ; Governor proportional error (hi byte)
  601. Gov_Prop_Pwm: .BYTE 1 ; Governor calculated new pwm based upon proportional error
  602. Gov_Arm_Target: .BYTE 1 ; Governor arm target value
  603. Wt_Advance_L: .BYTE 1 ; Timer3 counts for commutation advance timing (lo byte)
  604. Wt_Advance_H: .BYTE 1 ; Timer3 counts for commutation advance timing (hi byte)
  605. Wt_Zc_Scan_L: .BYTE 1 ; Timer3 counts from commutation to zero cross scan (lo byte)
  606. Wt_Zc_Scan_H: .BYTE 1 ; Timer3 counts from commutation to zero cross scan (hi byte)
  607. Wt_Comm_L: .BYTE 1 ; Timer3 counts from zero cross to commutation (lo byte)
  608. Wt_Comm_H: .BYTE 1 ; Timer3 counts from zero cross to commutation (hi byte)
  609. Rcp_PrePrev_Edge_L: .BYTE 1 ; RC pulse pre previous edge pca timestamp (lo byte)
  610. Rcp_PrePrev_Edge_H: .BYTE 1 ; RC pulse pre previous edge pca timestamp (hi byte)
  611. Rcp_Edge_L: .BYTE 1 ; RC pulse edge pca timestamp (lo byte)
  612. Rcp_Edge_H: .BYTE 1 ; RC pulse edge pca timestamp (hi byte)
  613. Rcp_Prev_Period_L: .BYTE 1 ; RC pulse previous period (lo byte)
  614. Rcp_Prev_Period_H: .BYTE 1 ; RC pulse previous period (hi byte)
  615. Rcp_Period_Diff_Accepted: .BYTE 1 ; RC pulse period difference acceptable
  616. New_Rcp: .BYTE 1 ; New RC pulse value in pca counts
  617. Prev_Rcp_Pwm_Freq: .BYTE 1 ; Previous RC pulse pwm frequency (used during pwm frequency measurement)
  618. Curr_Rcp_Pwm_Freq: .BYTE 1 ; Current RC pulse pwm frequency (used during pwm frequency measurement)
  619. Rcp_Stop_Cnt: .BYTE 1 ; Counter for RC pulses below stop value (lo byte)
  620. Auto_Bailout_Armed: .BYTE 1 ; Set when auto rotation bailout is armed
  621. Pwm_Limit: .BYTE 1 ; Maximum allowed pwm
  622. Pwm_Limit_Spoolup: .BYTE 1 ; Maximum allowed pwm during spoolup of main
  623. Pwm_Spoolup_Beg: .BYTE 1 ; Pwm to begin main spoolup with
  624. Pwm_Motor_Idle: .BYTE 1 ; Motor idle speed pwm
  625. Pwm_On_Cnt: .BYTE 1 ; Pwm on event counter (used to increase pwm off time for low pwm)
  626. Pwm_Off_Cnt: .BYTE 1 ; Pwm off event counter (used to run some pwm cycles without damping)
  627. Pwm_Prev_Edge: .BYTE 1 ; Timestamp from timer 2 when pwm toggles on or off
  628. Spoolup_Limit_Cnt: .BYTE 1 ; Interrupt count for spoolup limit
  629. Spoolup_Limit_Skip: .BYTE 1 ; Interrupt skips for spoolup limit increment (1=no skips, 2=skip one etc)
  630. Damping_Period: .BYTE 1 ; Damping on/off period
  631. Damping_On: .BYTE 1 ; Damping on part of damping period
  632. Lipo_Adc_Reference_L: .BYTE 1 ; Voltage reference adc value (lo byte)
  633. Lipo_Adc_Reference_H: .BYTE 1 ; Voltage reference adc value (hi byte)
  634. Lipo_Adc_Limit_L: .BYTE 1 ; Low voltage limit adc value (lo byte)
  635. Lipo_Adc_Limit_H: .BYTE 1 ; Low voltage limit adc value (hi byte)
  636. Adc_Conversion_Cnt: .BYTE 1 ; Adc conversion counter
  637. Current_Average_Temp_Adc: .BYTE 1 ; Current average temp ADC reading (lo byte of ADC, assuming hi byte is 0)
  638. Ppm_Throttle_Gain: .BYTE 1 ; Gain to be applied to RCP value for PPM input
  639. Beep_Strength: .BYTE 1 ; Strength of beeps
  640. Tx_Pgm_Func_No: .BYTE 1 ; Function number when doing programming by tx
  641. Tx_Pgm_Paraval_No: .BYTE 1 ; Parameter value number when doing programming by tx
  642. Tx_Pgm_Beep_No: .BYTE 1 ; Beep number when doing programming by tx
  643. ; The variables below must be in this sequence
  644. Pgm_Gov_P_Gain: .BYTE 1 ; Programmed governor P gain
  645. Pgm_Gov_I_Gain: .BYTE 1 ; Programmed governor I gain
  646. Pgm_Gov_Mode: .BYTE 1 ; Programmed governor mode
  647. Pgm_Low_Voltage_Lim: .BYTE 1 ; Programmed low voltage limit
  648. Pgm_Motor_Gain: .BYTE 1 ; Programmed motor gain
  649. Pgm_Motor_Idle: .BYTE 1 ; Programmed motor idle speed
  650. Pgm_Startup_Pwr: .BYTE 1 ; Programmed startup power
  651. Pgm_Pwm_Freq: .BYTE 1 ; Programmed pwm frequency
  652. Pgm_Direction: .BYTE 1 ; Programmed rotation direction
  653. Pgm_Input_Pol: .BYTE 1 ; Programmed input pwm polarity
  654. Initialized_L_Dummy: .BYTE 1 ; Place holder
  655. Initialized_H_Dummy: .BYTE 1 ; Place holder
  656. Pgm_Enable_TX_Program: .BYTE 1 ; Programmed enable/disable value for TX programming
  657. Pgm_Main_Rearm_Start: .BYTE 1 ; Programmed enable/disable re-arming main every start
  658. Pgm_Gov_Setup_Target: .BYTE 1 ; Programmed main governor setup target
  659. Pgm_Startup_Rpm: .BYTE 1 ; Programmed startup rpm
  660. Pgm_Startup_Accel: .BYTE 1 ; Programmed startup acceleration
  661. Pgm_Volt_Comp_Dummy: .BYTE 1 ; Place holder
  662. Pgm_Comm_Timing: .BYTE 1 ; Programmed commutation timing
  663. Pgm_Damping_Force: .BYTE 1 ; Programmed damping force
  664. Pgm_Gov_Range: .BYTE 1 ; Programmed governor range
  665. Pgm_Startup_Method: .BYTE 1 ; Programmed startup method
  666. Pgm_Ppm_Min_Throttle: .BYTE 1 ; Programmed throttle minimum
  667. Pgm_Ppm_Max_Throttle: .BYTE 1 ; Programmed throttle maximum
  668. Pgm_Beep_Strength: .BYTE 1 ; Programmed beep strength
  669. Pgm_Beacon_Strength: .BYTE 1 ; Programmed beacon strength
  670. Pgm_Beacon_Delay: .BYTE 1 ; Programmed beacon delay
  671. Pgm_Throttle_Rate: .BYTE 1 ; Programmed throttle rate
  672. Pgm_Demag_Comp: .BYTE 1 ; Programmed demag compensation
  673. Pgm_BEC_Voltage_High: .BYTE 1 ; Programmed BEC voltage
  674. Pgm_Ppm_Center_Throttle: .BYTE 1 ; Programmed throttle center (in bidirectional mode)
  675. ; The sequence of the variables below is no longer of importance
  676. Pgm_Gov_P_Gain_Decoded: .BYTE 1 ; Programmed governor decoded P gain
  677. Pgm_Gov_I_Gain_Decoded: .BYTE 1 ; Programmed governor decoded I gain
  678. Pgm_Throttle_Rate_Decoded: .BYTE 1 ; Programmed throttle rate decoded
  679. Pgm_Startup_Pwr_Decoded: .BYTE 1 ; Programmed startup power decoded
  680. Pgm_Demag_Comp_Power_Decoded: .BYTE 1 ; Programmed demag compensation power cut decoded
  681. .EQU SRAM_BYTES = 255 ; Bytes used in SRAM. Used for number of bytes to reset
  682. ;**** **** **** **** ****
  683. .ESEG ; Eeprom segment
  684. .ORG 0
  685. .EQU EEPROM_FW_MAIN_REVISION = 11 ; Main revision of the firmware
  686. .EQU EEPROM_FW_SUB_REVISION = 2 ; Sub revision of the firmware
  687. .EQU EEPROM_LAYOUT_REVISION = 17 ; Revision of the EEPROM layout
  688. Eep_FW_Main_Revision: .DB EEPROM_FW_MAIN_REVISION ; EEPROM firmware main revision number
  689. Eep_FW_Sub_Revision: .DB EEPROM_FW_SUB_REVISION ; EEPROM firmware sub revision number
  690. Eep_Layout_Revision: .DB EEPROM_LAYOUT_REVISION ; EEPROM layout revision number
  691. .IF MODE == 0
  692. Eep_Pgm_Gov_P_Gain: .DB DEFAULT_PGM_MAIN_P_GAIN ; EEPROM copy of programmed governor P gain
  693. Eep_Pgm_Gov_I_Gain: .DB DEFAULT_PGM_MAIN_I_GAIN ; EEPROM copy of programmed governor I gain
  694. Eep_Pgm_Gov_Mode: .DB DEFAULT_PGM_MAIN_GOVERNOR_MODE ; EEPROM copy of programmed governor mode
  695. Eep_Pgm_Low_Voltage_Lim: .DB DEFAULT_PGM_MAIN_LOW_VOLTAGE_LIM ; EEPROM copy of programmed low voltage limit
  696. _Eep_Pgm_Motor_Gain: .DB 0xFF
  697. _Eep_Pgm_Motor_Idle: .DB 0xFF
  698. Eep_Pgm_Startup_Pwr: .DB DEFAULT_PGM_MAIN_STARTUP_PWR ; EEPROM copy of programmed startup power
  699. Eep_Pgm_Pwm_Freq: .DB DEFAULT_PGM_MAIN_PWM_FREQ ; EEPROM copy of programmed pwm frequency
  700. Eep_Pgm_Direction: .DB DEFAULT_PGM_MAIN_DIRECTION ; EEPROM copy of programmed rotation direction
  701. Eep_Pgm_Input_Pol: .DB DEFAULT_PGM_MAIN_RCP_PWM_POL ; EEPROM copy of programmed input polarity
  702. Eep_Initialized_L: .DB 0xA5 ; EEPROM initialized signature low byte
  703. Eep_Initialized_H: .DB 0x5A ; EEPROM initialized signature high byte
  704. Eep_Enable_TX_Program: .DB DEFAULT_PGM_ENABLE_TX_PROGRAM ; EEPROM TX programming enable
  705. Eep_Main_Rearm_Start: .DB DEFAULT_PGM_MAIN_REARM_START ; EEPROM re-arming main enable
  706. Eep_Pgm_Gov_Setup_Target: .DB DEFAULT_PGM_MAIN_GOV_SETUP_TARGET ; EEPROM main governor setup target
  707. _Eep_Pgm_Startup_Rpm: .DB 0xFF
  708. _Eep_Pgm_Startup_Accel: .DB 0xFF
  709. _Eep_Pgm_Volt_Comp: .DB 0xFF
  710. Eep_Pgm_Comm_Timing: .DB DEFAULT_PGM_MAIN_COMM_TIMING ; EEPROM copy of programmed commutation timing
  711. Eep_Pgm_Damping_Force: .DB DEFAULT_PGM_MAIN_DAMPING_FORCE ; EEPROM copy of programmed damping force
  712. Eep_Pgm_Gov_Range: .DB DEFAULT_PGM_MAIN_GOVERNOR_RANGE ; EEPROM copy of programmed governor range
  713. _Eep_Pgm_Startup_Method: .DB 0xFF
  714. Eep_Pgm_Ppm_Min_Throttle: .DB DEFAULT_PGM_PPM_MIN_THROTTLE ; EEPROM copy of programmed minimum throttle (final value is 4x+1000=1148)
  715. Eep_Pgm_Ppm_Max_Throttle: .DB DEFAULT_PGM_PPM_MAX_THROTTLE ; EEPROM copy of programmed minimum throttle (final value is 4x+1000=1832)
  716. Eep_Pgm_Beep_Strength: .DB DEFAULT_PGM_MAIN_BEEP_STRENGTH ; EEPROM copy of programmed beep strength
  717. Eep_Pgm_Beacon_Strength: .DB DEFAULT_PGM_MAIN_BEACON_STRENGTH ; EEPROM copy of programmed beacon strength
  718. Eep_Pgm_Beacon_Delay: .DB DEFAULT_PGM_MAIN_BEACON_DELAY ; EEPROM copy of programmed beacon delay
  719. Eep_Pgm_Throttle_Rate: .DB DEFAULT_PGM_MAIN_THROTTLE_RATE ; EEPROM copy of programmed throttle rate
  720. Eep_Pgm_Demag_Comp: .DB DEFAULT_PGM_MAIN_DEMAG_COMP ; EEPROM copy of programmed demag compensation
  721. Eep_Pgm_BEC_Voltage_High: .DB DEFAULT_PGM_BEC_VOLTAGE_HIGH ; EEPROM copy of programmed BEC voltage
  722. _Eep_Pgm_Ppm_Center_Throttle: .DB 0xFF ; EEPROM copy of programmed center throttle (final value is 4x+1000=1488)
  723. .ENDIF
  724. .IF MODE == 1
  725. _Eep_Pgm_Gov_P_Gain: .DB 0xFF
  726. _Eep_Pgm_Gov_I_Gain: .DB 0xFF
  727. _Eep_Pgm_Gov_Mode: .DB 0xFF
  728. _Eep_Pgm_Low_Voltage_Lim: .DB 0xFF
  729. Eep_Pgm_Motor_Gain: .DB DEFAULT_PGM_TAIL_GAIN ; EEPROM copy of programmed tail gain
  730. Eep_Pgm_Motor_Idle: .DB DEFAULT_PGM_TAIL_IDLE_SPEED ; EEPROM copy of programmed tail idle speed
  731. Eep_Pgm_Startup_Pwr: .DB DEFAULT_PGM_TAIL_STARTUP_PWR ; EEPROM copy of programmed startup power
  732. Eep_Pgm_Pwm_Freq: .DB DEFAULT_PGM_TAIL_PWM_FREQ ; EEPROM copy of programmed pwm frequency
  733. Eep_Pgm_Direction: .DB DEFAULT_PGM_TAIL_DIRECTION ; EEPROM copy of programmed rotation direction
  734. Eep_Pgm_Input_Pol: .DB DEFAULT_PGM_TAIL_RCP_PWM_POL ; EEPROM copy of programmed input polarity
  735. Eep_Initialized_L: .DB 0x5A ; EEPROM initialized signature low byte
  736. Eep_Initialized_H: .DB 0xA5 ; EEPROM initialized signature high byte
  737. Eep_Enable_TX_Program: .DB DEFAULT_PGM_ENABLE_TX_PROGRAM ; EEPROM TX programming enable
  738. _Eep_Main_Rearm_Start: .DB 0xFF
  739. _Eep_Pgm_Gov_Setup_Target: .DB 0xFF
  740. _Eep_Pgm_Startup_Rpm: .DB 0xFF
  741. _Eep_Pgm_Startup_Accel: .DB 0xFF
  742. _Eep_Pgm_Volt_Comp: .DB 0xFF
  743. Eep_Pgm_Comm_Timing: .DB DEFAULT_PGM_TAIL_COMM_TIMING ; EEPROM copy of programmed commutation timing
  744. Eep_Pgm_Damping_Force: .DB DEFAULT_PGM_TAIL_DAMPING_FORCE ; EEPROM copy of programmed damping force
  745. _Eep_Pgm_Gov_Range: .DB 0xFF
  746. _Eep_Pgm_Startup_Method: .DB 0xFF
  747. Eep_Pgm_Ppm_Min_Throttle: .DB DEFAULT_PGM_PPM_MIN_THROTTLE ; EEPROM copy of programmed minimum throttle (final value is 4x+1000=1148)
  748. Eep_Pgm_Ppm_Max_Throttle: .DB DEFAULT_PGM_PPM_MAX_THROTTLE ; EEPROM copy of programmed minimum throttle (final value is 4x+1000=1832)
  749. Eep_Pgm_Beep_Strength: .DB DEFAULT_PGM_TAIL_BEEP_STRENGTH ; EEPROM copy of programmed beep strength
  750. Eep_Pgm_Beacon_Strength: .DB DEFAULT_PGM_TAIL_BEACON_STRENGTH ; EEPROM copy of programmed beacon strength
  751. Eep_Pgm_Beacon_Delay: .DB DEFAULT_PGM_TAIL_BEACON_DELAY ; EEPROM copy of programmed beacon delay
  752. Eep_Pgm_Throttle_Rate: .DB DEFAULT_PGM_TAIL_THROTTLE_RATE ; EEPROM copy of programmed throttle rate
  753. Eep_Pgm_Demag_Comp: .DB DEFAULT_PGM_TAIL_DEMAG_COMP ; EEPROM copy of programmed demag compensation
  754. Eep_Pgm_BEC_Voltage_High: .DB DEFAULT_PGM_BEC_VOLTAGE_HIGH ; EEPROM copy of programmed BEC voltage
  755. Eep_Pgm_Ppm_Center_Throttle: .DB DEFAULT_PGM_PPM_CENTER_THROTTLE ; EEPROM copy of programmed center throttle (final value is 4x+1000=1488)
  756. .ENDIF
  757. .IF MODE == 2
  758. Eep_Pgm_Gov_P_Gain: .DB DEFAULT_PGM_MULTI_P_GAIN ; EEPROM copy of programmed closed loop P gain
  759. Eep_Pgm_Gov_I_Gain: .DB DEFAULT_PGM_MULTI_I_GAIN ; EEPROM copy of programmed closed loop I gain
  760. Eep_Pgm_Gov_Mode: .DB DEFAULT_PGM_MULTI_GOVERNOR_MODE ; EEPROM copy of programmed closed loop mode
  761. Eep_Pgm_Low_Voltage_Lim: .DB DEFAULT_PGM_MULTI_LOW_VOLTAGE_LIM ; EEPROM copy of programmed low voltage limit
  762. Eep_Pgm_Motor_Gain: .DB DEFAULT_PGM_MULTI_GAIN ; EEPROM copy of programmed tail gain
  763. _Eep_Pgm_Motor_Idle: .DB 0xFF ; EEPROM copy of programmed tail idle speed
  764. Eep_Pgm_Startup_Pwr: .DB DEFAULT_PGM_MULTI_STARTUP_PWR ; EEPROM copy of programmed startup power
  765. Eep_Pgm_Pwm_Freq: .DB DEFAULT_PGM_MULTI_PWM_FREQ ; EEPROM copy of programmed pwm frequency
  766. Eep_Pgm_Direction: .DB DEFAULT_PGM_MULTI_DIRECTION ; EEPROM copy of programmed rotation direction
  767. Eep_Pgm_Input_Pol: .DB DEFAULT_PGM_MULTI_RCP_PWM_POL ; EEPROM copy of programmed input polarity
  768. Eep_Initialized_L: .DB 0x55 ; EEPROM initialized signature low byte
  769. Eep_Initialized_H: .DB 0xAA ; EEPROM initialized signature high byte
  770. Eep_Enable_TX_Program: .DB DEFAULT_PGM_ENABLE_TX_PROGRAM ; EEPROM TX programming enable
  771. _Eep_Main_Rearm_Start: .DB 0xFF
  772. _Eep_Pgm_Gov_Setup_Target: .DB 0xFF
  773. _Eep_Pgm_Startup_Rpm: .DB 0xFF
  774. _Eep_Pgm_Startup_Accel: .DB 0xFF
  775. _Eep_Pgm_Volt_Comp: .DB 0xFF
  776. Eep_Pgm_Comm_Timing: .DB DEFAULT_PGM_MULTI_COMM_TIMING ; EEPROM copy of programmed commutation timing
  777. Eep_Pgm_Damping_Force: .DB DEFAULT_PGM_MULTI_DAMPING_FORCE ; EEPROM copy of programmed damping force
  778. _Eep_Pgm_Gov_Range: .DB 0xFF
  779. _Eep_Pgm_Startup_Method: .DB 0xFF
  780. Eep_Pgm_Ppm_Min_Throttle: .DB DEFAULT_PGM_PPM_MIN_THROTTLE ; EEPROM copy of programmed minimum throttle (final value is 4x+1000=1148)
  781. Eep_Pgm_Ppm_Max_Throttle: .DB DEFAULT_PGM_PPM_MAX_THROTTLE ; EEPROM copy of programmed minimum throttle (final value is 4x+1000=1832)
  782. Eep_Pgm_Beep_Strength: .DB DEFAULT_PGM_MULTI_BEEP_STRENGTH ; EEPROM copy of programmed beep strength
  783. Eep_Pgm_Beacon_Strength: .DB DEFAULT_PGM_MULTI_BEACON_STRENGTH ; EEPROM copy of programmed beacon strength
  784. Eep_Pgm_Beacon_Delay: .DB DEFAULT_PGM_MULTI_BEACON_DELAY ; EEPROM copy of programmed beacon delay
  785. Eep_Pgm_Throttle_Rate: .DB DEFAULT_PGM_MULTI_THROTTLE_RATE ; EEPROM copy of programmed throttle rate
  786. Eep_Pgm_Demag_Comp: .DB DEFAULT_PGM_MULTI_DEMAG_COMP ; EEPROM copy of programmed demag compensation
  787. Eep_Pgm_BEC_Voltage_High: .DB DEFAULT_PGM_BEC_VOLTAGE_HIGH ; EEPROM copy of programmed BEC voltage
  788. Eep_Pgm_Ppm_Center_Throttle: .DB DEFAULT_PGM_PPM_CENTER_THROTTLE ; EEPROM copy of programmed center throttle (final value is 4x+1000=1488)
  789. .ENDIF
  790. Eep_Dummy: .DB 0xFF ; EEPROM address for safety reason
  791. .ORG 0x60
  792. Eep_Name: .DB " " ; Name tag (16 Bytes)
  793. ;**** **** **** **** ****
  794. .CSEG ; Code segment
  795. .ORG 0
  796. Interrupt_Table_Definition ; ATmega interrupts
  797. ;**** **** **** **** ****
  798. ; Table definitions
  799. GOV_GAIN_TABLE: .DB 0x02, 0x03, 0x04, 0x06, 0x08, 0x0C, 0x10, 0x18, 0x20, 0x30, 0x40, 0x60, 0x80, 0 ; Padded zero for an even number
  800. THROTTLE_RATE_TABLE: .DB 0x02, 0x03, 0x04, 0x06, 0x08, 0x0C, 0x10, 0x18, 0x20, 0x30, 0x40, 0x80, 0xFF, 0 ; Padded zero for an even number
  801. STARTUP_POWER_TABLE: .DB 0x04, 0x06, 0x08, 0x0C, 0x10, 0x18, 0x20, 0x30, 0x40, 0x60, 0x80, 0xA0, 0xC0, 0 ; Padded zero for an even number
  802. DEMAG_POWER_TABLE: .DB 0, 2, 1, 0 ; Padded zero for an even number
  803. .IF MODE == 0
  804. TX_PGM_PARAMS_MAIN: .DB 13, 13, 4, 3, 6, 13, 5, 13, 6, 3, 5, 2, 2, 0 ; Padded zero for an even number
  805. .ENDIF
  806. .IF MODE == 1
  807. .IF DAMPED_MODE_ENABLE == 1
  808. TX_PGM_PARAMS_TAIL: .DB 5, 5, 13, 5, 13, 6, 4, 5, 3, 2
  809. .ENDIF
  810. .IF DAMPED_MODE_ENABLE == 0
  811. TX_PGM_PARAMS_TAIL: .DB 5, 5, 13, 5, 13, 6, 3, 5, 3, 2
  812. .ENDIF
  813. .ENDIF
  814. .IF MODE == 2
  815. .IF DAMPED_MODE_ENABLE == 1
  816. TX_PGM_PARAMS_MULTI: .DB 13, 13, 4, 5, 6, 13, 5, 13, 6, 4, 5, 3, 2, 0 ; Padded zero for an even number
  817. .ENDIF
  818. .IF DAMPED_MODE_ENABLE == 0
  819. TX_PGM_PARAMS_MULTI: .DB 13, 13, 4, 5, 6, 13, 5, 13, 6, 3, 5, 3, 2, 0 ; Padded zero for an even number
  820. .ENDIF
  821. .ENDIF
  822. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  823. ;
  824. ; Timer2 interrupt routine
  825. ;
  826. ; Assumptions: Z register must be set to desired pwm_nfet_on label
  827. ; Requirements: I_Temp variables can NOT be used
  828. ;
  829. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  830. t2_int: ; Used for pwm control
  831. in II_Sreg, SREG
  832. ; Check if pwm is on
  833. sbrc Flags0, PWM_ON ; Is pwm on?
  834. rjmp t2_int_pwm_off
  835. ; Do not execute pwm when stopped
  836. sbrs Flags1, MOTOR_SPINNING
  837. rjmp t2_int_pwm_on_stopped
  838. ; Do not execute pwm on during demag recovery
  839. sbrc Flags0, DEMAG_CUT_POWER
  840. rjmp t2_int_pwm_on_stopped
  841. ; Pwm on cycle.
  842. sbrs Current_Pwm_Limited, 7 ; Jump for low pwm (<50%)
  843. rjmp t2_int_pwm_on_low_pwm
  844. t2_int_pwm_on_execute:
  845. ijmp ; Jump to pwm on routines. Z should be set to one of the pwm_nfet_on labels
  846. t2_int_pwm_on_low_pwm:
  847. .IF (MODE == 0) || (MODE == 2); Main or multi
  848. rjmp t2_int_pwm_on_execute
  849. .ENDIF
  850. .IF MODE == 1 ; Tail
  851. ; Skip pwm on cycles for very low pwm
  852. lds YL, Pwm_On_Cnt ; Increment event counter
  853. inc YL
  854. sts Pwm_On_Cnt, YL
  855. ldi YL, 5 ; Only skip for very low pwm
  856. sub YL, Current_Pwm_Limited ; Check skipping shall be done (for low pwm only)
  857. brcs t2_int_pwm_on_execute
  858. lds YH, Pwm_On_Cnt ; Check if on cycle is to be skipped
  859. sub YL, YH
  860. brcs t2_int_pwm_on_execute
  861. ldi YL, 120 ; Write start point for timer
  862. sec
  863. sbrc Flags2, PGM_PWM_HIGH_FREQ
  864. ror YL
  865. .IF CLK_8M == 1
  866. sec
  867. ror YL
  868. .ENDIF
  869. Set_TCNT2 YL
  870. mov YL, Current_Pwm_Limited
  871. tst YL
  872. brne t2_int_pwm_on_low_pwm_not_zero
  873. ldi YL, 0 ; Write start point for timer (long time for zero pwm)
  874. sbrc Flags2, PGM_PWM_HIGH_FREQ
  875. ldi YL, 0x80
  876. .IF CLK_8M == 1
  877. ldi YL, 0xC0
  878. .ENDIF
  879. Set_TCNT2 YL
  880. t2_int_pwm_on_low_pwm_not_zero:
  881. rjmp t2_int_pwm_on_exit_no_timer_update
  882. .ENDIF
  883. t2_int_pwm_on_stopped:
  884. rjmp t2_int_pwm_on_exit
  885. t2_int_pwm_off:
  886. sbrs Flags1, STARTUP_PHASE
  887. rjmp t2_int_pwm_off_start_checked
  888. All_nFETs_Off YL ; Switch off all nfets early during start, for a smooth start
  889. t2_int_pwm_off_start_checked:
  890. ; Pwm off cycle
  891. mov YL, Current_Pwm_Limited
  892. sec
  893. sbrc Flags2, PGM_PWM_HIGH_FREQ ; Use half the time when pwm frequency is high
  894. ror YL
  895. .IF CLK_8M == 1
  896. sec
  897. ror YL
  898. .ENDIF
  899. Set_TCNT2 YL ; Load new timer setting
  900. sts Pwm_Prev_Edge, YL ; Set timestamp
  901. ; Clear pwm on flag
  902. cbr Flags0, (1<<PWM_ON)
  903. ; Set full PWM (on all the time) if current PWM near max. This will give full power, but at the cost of a small "jump" in power
  904. mov YL, Current_Pwm_Limited ; Load current pwm
  905. cpi YL, 0xFF ; Full pwm?
  906. brne PC+2 ; No - branch
  907. rjmp t2_int_pwm_off_fullpower_exit ; Yes - exit
  908. lds YL, Pwm_Off_Cnt ; Increment event counter
  909. inc YL
  910. sts Pwm_Off_Cnt, YL
  911. ; Do not execute pwm when stopped
  912. sbrs Flags1, MOTOR_SPINNING
  913. rjmp t2_int_pwm_off_stopped
  914. ; If damped operation, set pFETs on in pwm_off
  915. sbrc Flags2, PGM_PWMOFF_DAMPED ; Damped operation?
  916. rjmp t2_int_pwm_off_damped
  917. ; Separate exit commands here for minimum delay
  918. All_nFETs_Off YL ; Switch off all nfets
  919. out SREG, II_Sreg
  920. reti
  921. t2_int_pwm_off_stopped:
  922. All_nFETs_Off YL ; Switch off all nfets
  923. rjmp t2_int_pwm_off_exit
  924. t2_int_pwm_off_damped:
  925. sbr Flags1, (1<<CURR_PWMOFF_DAMPED) ; Set damped status
  926. cbr Flags1, (1<<CURR_PWMOFF_COMP_ABLE) ; Set comparator unusable status
  927. lds YL, Damping_On
  928. tst YL
  929. breq t2_int_pwm_off_do_damped ; Highest damping - apply damping always
  930. lds YL, Pwm_Off_Cnt ; Is damped on number reached?
  931. dec YL
  932. lds YH, Damping_On
  933. sub YL, YH
  934. brcs t2_int_pwm_off_do_damped ; No - apply damping
  935. cbr Flags1, (1<<CURR_PWMOFF_DAMPED) ; Set non damped status
  936. sbr Flags1, (1<<CURR_PWMOFF_COMP_ABLE) ; Set comparator usable status
  937. lds YL, Pwm_Off_Cnt
  938. lds YH, Damping_Period ; Is damped period number reached?
  939. sub YL, YH
  940. brcc t2_int_pwm_off_clr_cnt ; Yes - Proceed
  941. rjmp t2_int_pwm_off_exit ; No - Branch
  942. t2_int_pwm_off_clr_cnt:
  943. sts Pwm_Off_Cnt, Zero ; Yes - clear counter
  944. rjmp t2_int_pwm_off_exit ; Not damped cycle - exit
  945. t2_int_pwm_off_do_damped:
  946. ; Delay to allow nFETs to go off before pFETs are turned on (only in full damped mode)
  947. sbrc Flags2, PGM_PWMOFF_DAMPED_LIGHT ; If damped light operation - branch
  948. rjmp t2_int_pwm_off_damped_light
  949. All_nFETs_Off YL ; Switch off all nfets
  950. ldi YL, PFETON_DELAY
  951. dec YL
  952. brne PC-1
  953. All_pFETs_On YL ; Switch on all pfets
  954. rjmp t2_int_pwm_off_exit
  955. t2_int_pwm_off_damped_light:
  956. .IF DAMPED_MODE_ENABLE == 1
  957. sbr Flags1, (1<<CURR_PWMOFF_COMP_ABLE) ; Set comparator usable status always for damped light mode on fully damped capable escs
  958. .ENDIF
  959. All_nFETs_Off YL ; Switch off all nfets
  960. lds YL, Comm_Phase ; Turn on pfets according to commutation phase
  961. sbrc YL, 2
  962. rjmp t2_int_pwm_off_comm_4_5_6
  963. sbrc YL, 1
  964. rjmp t2_int_pwm_off_comm_2_3
  965. .IF DAMPED_MODE_ENABLE == 0
  966. ApFET_On ; Comm phase 1 - turn on A
  967. .ELSE
  968. ldi YL, PFETON_DELAY
  969. dec YL
  970. brne PC-1
  971. CpFET_On ; Comm phase 1 - turn on C
  972. .ENDIF
  973. rjmp t2_int_pwm_off_exit
  974. t2_int_pwm_off_comm_2_3:
  975. sbrc YL, 0
  976. rjmp t2_int_pwm_off_comm_3
  977. .IF DAMPED_MODE_ENABLE == 0
  978. BpFET_On ; Comm phase 2 - turn on B
  979. .ELSE
  980. ldi YL, PFETON_DELAY
  981. dec YL
  982. brne PC-1
  983. CpFET_On ; Comm phase 2 - turn on C
  984. .ENDIF
  985. rjmp t2_int_pwm_off_exit
  986. t2_int_pwm_off_comm_3:
  987. .IF DAMPED_MODE_ENABLE == 0
  988. CpFET_On ; Comm phase 3 - turn on C
  989. .ELSE
  990. ldi YL, PFETON_DELAY
  991. dec YL
  992. brne PC-1
  993. BpFET_On ; Comm phase 3 - turn on B
  994. .ENDIF
  995. rjmp t2_int_pwm_off_exit
  996. t2_int_pwm_off_comm_4_5_6:
  997. sbrc YL, 1
  998. rjmp t2_int_pwm_off_comm_6
  999. sbrc YL, 0
  1000. rjmp t2_int_pwm_off_comm_5
  1001. .IF DAMPED_MODE_ENABLE == 0
  1002. ApFET_On ; Comm phase 4 - turn on A
  1003. .ELSE
  1004. ldi YL, PFETON_DELAY
  1005. dec YL
  1006. brne PC-1
  1007. BpFET_On ; Comm phase 4 - turn on B
  1008. .ENDIF
  1009. rjmp t2_int_pwm_off_exit
  1010. t2_int_pwm_off_comm_5:
  1011. .IF DAMPED_MODE_ENABLE == 0
  1012. BpFET_On ; Comm phase 5 - turn on B
  1013. .ELSE
  1014. ldi YL, PFETON_DELAY
  1015. dec YL
  1016. brne PC-1
  1017. ApFET_On ; Comm phase 5 - turn on A
  1018. .ENDIF
  1019. rjmp t2_int_pwm_off_exit
  1020. t2_int_pwm_off_comm_6:
  1021. .IF DAMPED_MODE_ENABLE == 0
  1022. CpFET_On ; Comm phase 6 - turn on C
  1023. .ELSE
  1024. ldi YL, PFETON_DELAY
  1025. dec YL
  1026. brne PC-1
  1027. ApFET_On ; Comm phase 6 - turn on A
  1028. .ENDIF
  1029. t2_int_pwm_off_exit: ; Exit from pwm off cycle
  1030. All_nFETs_Off YL ; Switch off all nfets
  1031. out SREG, II_Sreg
  1032. reti
  1033. t2_int_pwm_off_fullpower_exit: ; Exit from pwm off cycle, leaving power on
  1034. out SREG, II_Sreg
  1035. reti
  1036. pwm_nofet_on: ; Dummy pwm on cycle
  1037. rjmp t2_int_pwm_on_exit
  1038. pwm_afet_on: ; Pwm on cycle afet on (bfet off)
  1039. AnFET_on
  1040. BnFET_off
  1041. rjmp t2_int_pwm_on_exit
  1042. pwm_bfet_on: ; Pwm on cycle bfet on (cfet off)
  1043. BnFET_on
  1044. CnFET_off
  1045. rjmp t2_int_pwm_on_exit
  1046. pwm_cfet_on: ; Pwm on cycle cfet on (afet off)
  1047. CnFET_on
  1048. AnFET_off
  1049. rjmp t2_int_pwm_on_exit
  1050. pwm_anfet_bpfet_on_fast: ; Pwm on cycle anfet on (bnfet off) and bpfet on (used in damped state 6)
  1051. ApFET_off
  1052. AnFET_on ; Switch nFETs
  1053. CpFET_off
  1054. BnFET_off
  1055. rjmp t2_int_pwm_on_exit
  1056. pwm_anfet_bpfet_on_safe: ; Pwm on cycle anfet on (bnfet off) and bpfet on (used in damped state 6)
  1057. ; Delay from pFETs are turned off (only in damped mode) until nFET is turned on (pFETs are slow)
  1058. ApFET_off
  1059. CpFET_off
  1060. ldi YL, PFETON_DELAY ; Set full delay
  1061. dec YL
  1062. brne PC-1
  1063. AnFET_on ; Switch nFETs
  1064. BnFET_off
  1065. rjmp t2_int_pwm_on_exit
  1066. pwm_anfet_cpfet_on_fast: ; Pwm on cycle anfet on (bnfet off) and cpfet on (used in damped state 5)
  1067. ApFET_off
  1068. AnFET_on ; Switch nFETs
  1069. BpFET_off
  1070. BnFET_off
  1071. rjmp t2_int_pwm_on_exit
  1072. pwm_anfet_cpfet_on_safe: ; Pwm on cycle anfet on (bnfet off) and cpfet on (used in damped state 5)
  1073. ; Delay from pFETs are turned off (only in damped mode) until nFET is turned on (pFETs are slow)
  1074. ApFET_off
  1075. BpFET_off
  1076. ldi YL, PFETON_DELAY ; Set full delay
  1077. dec YL
  1078. brne PC-1
  1079. AnFET_on ; Switch nFETs
  1080. BnFET_off
  1081. rjmp t2_int_pwm_on_exit
  1082. pwm_bnfet_cpfet_on_fast: ; Pwm on cycle bnfet on (cnfet off) and cpfet on (used in damped state 4)
  1083. BpFET_off
  1084. BnFET_on ; Switch nFETs
  1085. ApFET_off
  1086. CnFET_off
  1087. rjmp t2_int_pwm_on_exit
  1088. pwm_bnfet_cpfet_on_safe: ; Pwm on cycle bnfet on (cnfet off) and cpfet on (used in damped state 4)
  1089. ; Delay from pFETs are turned off (only in damped mode) until nFET is turned on (pFETs are slow)
  1090. BpFET_off
  1091. ApFET_off
  1092. ldi YL, PFETON_DELAY ; Set full delay
  1093. dec YL
  1094. brne PC-1
  1095. BnFET_on ; Switch nFETs
  1096. CnFET_off
  1097. rjmp t2_int_pwm_on_exit
  1098. pwm_bnfet_apfet_on_fast: ; Pwm on cycle bnfet on (cnfet off) and apfet on (used in damped state 3)
  1099. BpFET_off
  1100. BnFET_on ; Switch nFETs
  1101. CpFET_off
  1102. CnFET_off
  1103. rjmp t2_int_pwm_on_exit
  1104. pwm_bnfet_apfet_on_safe: ; Pwm on cycle bnfet on (cnfet off) and apfet on (used in damped state 3)
  1105. ; Delay from pFETs are turned off (only in damped mode) until nFET is turned on (pFETs are slow)
  1106. BpFET_off
  1107. CpFET_off
  1108. ldi YL, PFETON_DELAY ; Set full delay
  1109. dec YL
  1110. brne PC-1
  1111. BnFET_on ; Switch nFETs
  1112. CnFET_off
  1113. rjmp t2_int_pwm_on_exit
  1114. pwm_cnfet_apfet_on_fast: ; Pwm on cycle cnfet on (anfet off) and apfet on (used in damped state 2)
  1115. CpFET_off
  1116. CnFET_on ; Switch nFETs
  1117. BpFET_off
  1118. AnFET_off
  1119. rjmp t2_int_pwm_on_exit
  1120. pwm_cnfet_apfet_on_safe: ; Pwm on cycle cnfet on (anfet off) and apfet on (used in damped state 2)
  1121. ; Delay from pFETs are turned off (only in damped mode) until nFET is turned on (pFETs are slow)
  1122. CpFET_off
  1123. BpFET_off
  1124. ldi YL, PFETON_DELAY ; Set full delay
  1125. dec YL
  1126. brne PC-1
  1127. CnFET_on ; Switch nFETs
  1128. AnFET_off
  1129. rjmp t2_int_pwm_on_exit
  1130. pwm_cnfet_bpfet_on_fast: ; Pwm on cycle cnfet on (anfet off) and bpfet on (used in damped state 1)
  1131. CpFET_off
  1132. CnFET_on ; Switch nFETs
  1133. ApFET_off
  1134. AnFET_off
  1135. rjmp t2_int_pwm_on_exit
  1136. pwm_cnfet_bpfet_on_safe: ; Pwm on cycle cnfet on (anfet off) and bpfet on (used in damped state 1)
  1137. ; Delay from pFETs are turned off (only in damped mode) until nFET is turned on (pFETs are slow)
  1138. CpFET_off
  1139. ApFET_off
  1140. ldi YL, PFETON_DELAY ; Set full delay
  1141. dec YL
  1142. brne PC-1
  1143. CnFET_on ; Switch nFETs
  1144. AnFET_off
  1145. rjmp t2_int_pwm_on_exit
  1146. t2_int_pwm_on_exit:
  1147. ; Set timer for coming on cycle length
  1148. mov YL, Current_Pwm_Limited ; Load current pwm
  1149. com YL ; com is 255-x
  1150. sec
  1151. sbrc Flags2, PGM_PWM_HIGH_FREQ ; Use half the time when pwm frequency is high
  1152. ror YL
  1153. .IF CLK_8M == 1
  1154. sec
  1155. ror YL
  1156. .ENDIF
  1157. Set_TCNT2 YL ; Write start point for timer
  1158. ; Set other variables
  1159. sts Pwm_Prev_Edge, YL ; Set timestamp
  1160. sts Pwm_On_Cnt, Zero ; Reset pwm on event counter
  1161. sbr Flags0, (1<<PWM_ON) ; Set pwm on flag
  1162. t2_int_pwm_on_exit_no_timer_update:
  1163. ; Exit interrupt
  1164. out SREG, II_Sreg
  1165. reti
  1166. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  1167. ;
  1168. ; Timer 1 output compare A interrupt
  1169. ;
  1170. ; No assumptions
  1171. ;
  1172. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  1173. t1oca_int:
  1174. in II_Sreg, SREG
  1175. T1oca_Clear_Int_Flag YL ; Clear interrupt flag if set
  1176. cbr Flags0, (1<<OC1A_PENDING) ; Flag that OC1A value is passed
  1177. out SREG, II_Sreg
  1178. reti
  1179. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  1180. ;
  1181. ; Timer0 interrupt routine
  1182. ;
  1183. ; No assumptions
  1184. ;
  1185. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  1186. t0_int: ; Happens every 128us
  1187. in I_Sreg, SREG
  1188. ; Disable RCP interrupts
  1189. cbr Flags2, (1<<RCP_INT_NESTED_ENABLED) ; Set flag default to disabled
  1190. Get_Rcp_Int_Enable_State XL ; Get rcp interrupt state
  1191. cpse XL, Zero
  1192. sbr Flags2, (1<<RCP_INT_NESTED_ENABLED) ; Set flag to enabled
  1193. Rcp_Int_Disable XL ; Disable rcp interrupts
  1194. T0_Int_Disable XL ; Disable timer0 interrupts
  1195. sei ; Enable interrupts
  1196. ; Check RC pulse timeout counter
  1197. lds XL, Rcp_Timeout_Cnt ; RC pulse timeout count zero?
  1198. tst XL
  1199. breq t0_int_pulses_absent ; Yes - pulses are absent
  1200. ; Decrement timeout counter (if PWM)
  1201. mov XL, Flags3 ; Check pwm frequency flags
  1202. andi XL, ((1<<RCP_PWM_FREQ_1KHZ)+(1<<RCP_PWM_FREQ_2KHZ)+(1<<RCP_PWM_FREQ_4KHZ)+(1<<RCP_PWM_FREQ_8KHZ)+(1<<RCP_PWM_FREQ_12KHZ))
  1203. breq t0_int_skip_start ; If no flag is set (PPM) - branch
  1204. lds XL, Rcp_Timeout_Cnt ; No - decrement
  1205. dec XL
  1206. sts Rcp_Timeout_Cnt, XL
  1207. rjmp t0_int_skip_start
  1208. t0_int_pulses_absent:
  1209. ; Timeout counter has reached zero, pulses are absent
  1210. ldi I_Temp1, RCP_MIN ; RCP_MIN as default
  1211. ldi I_Temp2, RCP_MIN
  1212. Read_Rcp_Int XL ; Look at value of Rcp_In
  1213. sbrc XL, Rcp_In ; Is it high?
  1214. ldi I_Temp1, RCP_MAX ; Yes - set RCP_MAX
  1215. Rcp_Int_First XL ; Set interrupt trig to first again
  1216. Rcp_Clear_Int_Flag XL ; Clear interrupt flag
  1217. cbr Flags2, (1<<RCP_EDGE_NO) ; Set first edge flag
  1218. Read_Rcp_Int XL ; Look once more at value of Rcp_In
  1219. sbrc XL, Rcp_In ; Is it high?
  1220. ldi I_Temp2, RCP_MAX ; Yes - set RCP_MAX
  1221. cp I_Temp1, I_Temp2
  1222. brne t0_int_pulses_absent ; Go back if they are not equal
  1223. ldi XL, RCP_TIMEOUT ; Load timeout count
  1224. sbrc Flags0, RCP_MEAS_PWM_FREQ ; Is measure RCP pwm frequency flag set?
  1225. sts Rcp_Timeout_Cnt, XL ; Yes - set timeout count to start value
  1226. mov XL, Flags3 ; Check pwm frequency flags
  1227. andi XL, ((1<<RCP_PWM_FREQ_1KHZ)+(1<<RCP_PWM_FREQ_2KHZ)+(1<<RCP_PWM_FREQ_4KHZ)+(1<<RCP_PWM_FREQ_8KHZ)+(1<<RCP_PWM_FREQ_12KHZ))
  1228. breq t0_int_ppm_timeout_set ; If no flag is set (PPM) - branch
  1229. ldi XL, RCP_TIMEOUT ; For PWM, set timeout count to start value
  1230. sts Rcp_Timeout_Cnt, XL
  1231. t0_int_ppm_timeout_set:
  1232. sts New_Rcp, I_Temp1 ; Store new pulse length
  1233. sbr Flags2, (1<<RCP_UPDATED) ; Set updated flag
  1234. t0_int_skip_start:
  1235. ; Check RC pulse skip counter
  1236. lds XL, Rcp_Skip_Cnt
  1237. tst XL
  1238. breq t0_int_skip_end ; If RC pulse skip count is zero - end skipping RC pulse detection
  1239. ; Decrement skip counter (only if edge counter is zero)
  1240. lds XL, Rcp_Skip_Cnt ; Decrement
  1241. dec XL
  1242. sts Rcp_Skip_Cnt, XL
  1243. rjmp t0_int_rcp_update_start
  1244. t0_int_skip_end:
  1245. mov XL, Flags3 ; Check pwm frequency flags
  1246. andi XL, ((1<<RCP_PWM_FREQ_1KHZ)+(1<<RCP_PWM_FREQ_2KHZ)+(1<<RCP_PWM_FREQ_4KHZ)+(1<<RCP_PWM_FREQ_8KHZ)+(1<<RCP_PWM_FREQ_12KHZ))
  1247. breq t0_int_rcp_update_start ; If no flag is set (PPM) - branch
  1248. ; Skip counter has reached zero, start looking for RC pulses again
  1249. sbr Flags2, (1<<RCP_INT_NESTED_ENABLED) ; Set flag to enabled
  1250. Rcp_Clear_Int_Flag XL ; Clear interrupt flag
  1251. t0_int_rcp_update_start:
  1252. ; Process updated RC pulse
  1253. sbrs Flags2, RCP_UPDATED ; Is there an updated RC pulse available?
  1254. rjmp t0_int_pwm_exit ; No - exit
  1255. lds XL, New_Rcp ; Load new pulse value
  1256. mov I_Temp1, XL
  1257. cbr Flags2, (1<<RCP_UPDATED) ; Flag that pulse has been evaluated
  1258. ; Use a gain of 1.0625x for pwm input if not governor mode
  1259. mov XL, Flags3 ; Check pwm frequency flags
  1260. andi XL, ((1<<RCP_PWM_FREQ_1KHZ)+(1<<RCP_PWM_FREQ_2KHZ)+(1<<RCP_PWM_FREQ_4KHZ)+(1<<RCP_PWM_FREQ_8KHZ)+(1<<RCP_PWM_FREQ_12KHZ))
  1261. breq t0_int_pwm_min_run ; If no flag is set (PPM) - branch
  1262. .IF MODE == 0 ; Main - do not adjust gain
  1263. rjmp t0_int_pwm_min_run
  1264. .ENDIF
  1265. .IF MODE == 2 ; Multi
  1266. lds XL, Pgm_Gov_Mode ; Closed loop mode?
  1267. cpi XL, 4
  1268. brne t0_int_pwm_min_run ; Yes - branch
  1269. .ENDIF
  1270. ; Limit the maximum value to avoid wrap when scaled to pwm range
  1271. cpi I_Temp1, 240 ; 240 = (255/1.0625) Needs to be updated according to multiplication factor below
  1272. brcs t0_int_rcp_update_mult
  1273. ldi I_Temp1, 240 ; Set requested pwm to max
  1274. t0_int_rcp_update_mult:
  1275. ; Multiply by 1.0625 (optional adjustment gyro gain)
  1276. mov XL, I_Temp1
  1277. swap XL ; After this "0.0625"
  1278. andi XL, 0x0F
  1279. add I_Temp1, XL
  1280. ; Adjust tail gain
  1281. lds I_Temp2, Pgm_Motor_Gain ; Is gain 1?
  1282. cpi I_Temp2, 3
  1283. breq t0_int_pwm_min_run ; Yes - skip adjustment
  1284. lsr XL ; After this "0.5"
  1285. lsr XL ; After this "0.25"
  1286. sbrc I_Temp2, 0 ; (I_Temp2 has Pgm_Motor_Gain)
  1287. rjmp t0_int_rcp_gain_corr ; Branch if bit 0 in gain is set
  1288. lsr XL ; After this "0.125"
  1289. t0_int_rcp_gain_corr:
  1290. sbrc I_Temp2, 2 ; (I_Temp2 has Pgm_Motor_Gain)
  1291. rjmp t0_int_rcp_gain_pos ; Branch if bit 2 in gain is set
  1292. sub XL, I_Temp1 ; Apply negative correction
  1293. mov I_Temp1, XL
  1294. rjmp t0_int_pwm_min_run
  1295. t0_int_rcp_gain_pos:
  1296. add I_Temp1, XL ; Apply positive correction
  1297. brcc t0_int_pwm_min_run ; Above max?
  1298. ldi I_Temp1, 0xFF ; Yes - limit
  1299. t0_int_pwm_min_run:
  1300. .IF MODE == 1 ; Tail - limit minimum pwm
  1301. ; Limit minimum pwm
  1302. lds XL, Pwm_Motor_Idle ; Is requested pwm lower than minimum?
  1303. cp I_Temp1, XL
  1304. brcc t0_int_pwm_update ; No - branch
  1305. mov I_Temp1, XL ; Yes - limit pwm to Pwm_Motor_Idle
  1306. .ENDIF
  1307. t0_int_pwm_update:
  1308. ; Update requested_pwm
  1309. sts Requested_Pwm, I_Temp1 ; Set requested pwm
  1310. ; Limit pwm during start
  1311. sbrs Flags1, STARTUP_PHASE
  1312. rjmp t0_int_current_pwm_update
  1313. lds XL, Requested_Pwm ; Limit pwm during start
  1314. lds I_Temp2, Pwm_Limit
  1315. cp XL, I_Temp2
  1316. brcs t0_int_current_pwm_update
  1317. sts Requested_Pwm, I_Temp2
  1318. t0_int_current_pwm_update:
  1319. .IF MODE == 0 || MODE == 2 ; Main or multi
  1320. lds I_Temp1, Pgm_Gov_Mode ; Governor mode?
  1321. cpi I_Temp1, 4
  1322. brne t0_int_pwm_exit ; Yes - branch
  1323. .ENDIF
  1324. ; Update current pwm, with limited throttle change rate
  1325. lds XL, Requested_Pwm ; Is requested pwm larger than current pwm?
  1326. lds I_Temp1, Current_Pwm
  1327. sub XL, I_Temp1
  1328. brcs t0_int_set_current_pwm ; No - proceed
  1329. lds I_Temp1, Pgm_Throttle_Rate_Decoded
  1330. sbc XL, I_Temp1 ; Is difference larger than throttle change rate?
  1331. brcs t0_int_set_current_pwm ; No - proceed
  1332. lds XL, Current_Pwm ; Increase current pwm by throttle change rate
  1333. add XL, I_Temp1
  1334. sts Current_Pwm, XL
  1335. brcc t0_int_current_pwm_done ; Is result above max?
  1336. ldi XL, 0xFF ; Yes - limit
  1337. sts Current_Pwm, XL
  1338. rjmp t0_int_current_pwm_done
  1339. t0_int_set_current_pwm:
  1340. lds XL, Requested_Pwm ; Set equal as default
  1341. sts Current_Pwm, XL
  1342. t0_int_current_pwm_done:
  1343. .IF MODE >= 1 ; Tail or multi
  1344. ; Set current_pwm_limited
  1345. lds I_Temp1, Current_Pwm ; Default not limited
  1346. lds XL, Pwm_Limit ; Check against limit
  1347. cp I_Temp1, XL
  1348. brcs PC+2 ; If current pwm below limit - branch
  1349. mov I_Temp1, XL ; Limit pwm
  1350. mov Current_Pwm_Limited, I_Temp1
  1351. .ENDIF
  1352. t0_int_pwm_exit:
  1353. ; Increment counter and check if high "interrupt"
  1354. lds XL, Timer0_Int_Cnt
  1355. inc XL
  1356. sts Timer0_Int_Cnt, XL
  1357. breq t0h_int
  1358. cli ; Disable interrupts
  1359. T0_Int_Enable XL ; Enable timer0 interrupts
  1360. sbrs Flags2, RCP_INT_NESTED_ENABLED; Restore rcp interrupt state
  1361. rjmp t0_int_pwm_ret
  1362. Rcp_Int_Enable XL
  1363. t0_int_pwm_ret:
  1364. out SREG, I_Sreg
  1365. reti
  1366. t0h_int:
  1367. ; Every 256th interrupt (happens every 32ms)
  1368. ldi I_Temp1, GOV_SPOOLRATE ; Load governor spool rate
  1369. ; Check RC pulse timeout counter (used here for PPM only)
  1370. lds I_Temp2, Rcp_Timeout_Cnt ; RC pulse timeout count zero?
  1371. tst I_Temp2
  1372. breq t0h_int_rcp_stop_check ; Yes - do not decrement
  1373. ; Decrement timeout counter (if PPM)
  1374. mov XL, Flags3 ; Check pwm frequency flags
  1375. andi XL, ((1<<RCP_PWM_FREQ_1KHZ)+(1<<RCP_PWM_FREQ_2KHZ)+(1<<RCP_PWM_FREQ_4KHZ)+(1<<RCP_PWM_FREQ_8KHZ)+(1<<RCP_PWM_FREQ_12KHZ))
  1376. brne t0h_int_rcp_stop_check ; If a flag is set (PWM) - branch
  1377. dec I_Temp2 ; No flag set (PPM) - decrement
  1378. sts Rcp_Timeout_Cnt, I_Temp2
  1379. t0h_int_rcp_stop_check:
  1380. ; Check RC pulse against stop value
  1381. lds XL, New_Rcp ; Load new pulse value
  1382. cpi XL, RCP_STOP ; Check if pulse is below stop value
  1383. brcs t0h_int_rcp_stop
  1384. ; RC pulse higher than stop value, reset stop counter
  1385. sts Rcp_Stop_Cnt, Zero ; Reset rcp stop counter
  1386. rjmp t0h_int_rcp_gov_pwm
  1387. t0h_int_rcp_stop:
  1388. ; RC pulse less than stop value
  1389. sts Auto_Bailout_Armed, Zero ; Disarm bailout
  1390. sts Spoolup_Limit_Cnt, Zero
  1391. lds XL, Rcp_Stop_Cnt ; Increment stop counter
  1392. subi XL, 0xFF ; Subtract minus one
  1393. sts Rcp_Stop_Cnt, XL
  1394. brcs t0h_int_rcp_gov_pwm ; Branch if counter has not wrapped
  1395. ldi XL, 0xFF ; Set stop counter to max
  1396. sts Rcp_Stop_Cnt, XL
  1397. t0h_int_rcp_gov_pwm:
  1398. .IF MODE == 0 ; Main
  1399. ; Update governor variables
  1400. lds I_Temp4, Requested_Pwm ; Load requested pwm
  1401. lds I_Temp2, Pgm_Gov_Mode ; Governor target by arm mode?
  1402. cpi I_Temp2, 2
  1403. brne t0h_int_rcp_gov_by_setup ; No - branch
  1404. sbrs Flags0, GOV_ACTIVE ; Is governor active?
  1405. breq t0h_int_rcp_gov_by_tx ; No - branch (this ensures soft spoolup by tx)
  1406. ldi XL, 50
  1407. cp I_Temp4, XL ; Is requested pwm below 20%? (Requested_Pwm in I_Temp4)
  1408. brcs t0h_int_rcp_gov_by_tx ; Yes - branch (this enables a soft spooldown)
  1409. lds XL, Gov_Arm_Target ; Yes - load arm target
  1410. sts Requested_Pwm, XL
  1411. t0h_int_rcp_gov_by_setup:
  1412. cpi I_Temp2, 3 ; Governor target by setup mode? (Pgm_Gov_Mode in I_Temp2)
  1413. brne t0h_int_rcp_gov_by_tx ; No - branch
  1414. sbrs Flags0, GOV_ACTIVE ; Is governor active?
  1415. breq t0h_int_rcp_gov_by_tx ; No - branch (this ensures soft spoolup by tx)
  1416. ldi XL, 50
  1417. cp I_Temp4, XL ; Is requested pwm below 20%? (Requested_Pwm in I_Temp4)
  1418. brcs t0h_int_rcp_gov_by_tx ; Yes - branch (this enables a soft spooldown)
  1419. lds XL, Pgm_Gov_Setup_Target ; Gov by setup - load setup target
  1420. sts Requested_Pwm, XL
  1421. t0h_int_rcp_gov_by_tx:
  1422. lds I_Temp2, Governor_Req_Pwm
  1423. cp I_Temp2, I_Temp4 ; Is governor requested pwm equal to requested pwm? (Requested_Pwm in I_Temp4)
  1424. breq t0h_int_rcp_gov_pwm_done ; Yes - branch
  1425. brcs t0h_int_rcp_gov_pwm_inc ; No - if lower, then increment
  1426. dec I_Temp2 ; No - if higher, then decrement
  1427. rjmp t0h_int_rcp_gov_pwm_done
  1428. t0h_int_rcp_gov_pwm_inc:
  1429. inc I_Temp2 ; Increment
  1430. t0h_int_rcp_gov_pwm_done:
  1431. sts Governor_Req_Pwm, I_Temp2 ; Store governor requested pwm
  1432. dec I_Temp1 ; Decrement spoolrate variable
  1433. brne t0h_int_rcp_gov_pwm ; If not number of steps processed - go back
  1434. lds I_Temp2, Spoolup_Limit_Cnt ; Load spoolup count
  1435. inc I_Temp2 ; Increment
  1436. brne PC+2 ; Wrapped?
  1437. dec I_Temp2 ; Yes - decrement
  1438. sts Spoolup_Limit_Cnt, I_Temp2
  1439. lds XL, Spoolup_Limit_Skip ; Load skip count
  1440. dec XL ; Decrement
  1441. sts Spoolup_Limit_Skip, XL ; Store skip count
  1442. breq PC+2
  1443. rjmp t0h_int_rcp_exit ; Jump if skip count is not reached
  1444. ldi XL, 1 ; Reset skip count. Default is fast spoolup
  1445. sts Spoolup_Limit_Skip, XL
  1446. ldi I_Temp1, 5 ; Default fast increase
  1447. cpi I_Temp2, (3*MAIN_SPOOLUP_TIME) ; No spoolup until "30"*32ms (Spoolup_Limit_Cnt in I_Temp2)
  1448. brcs t0h_int_rcp_exit
  1449. cpi I_Temp2, (10*MAIN_SPOOLUP_TIME) ; Slow spoolup until "100"*32ms (Spoolup_Limit_Cnt in I_Temp2)
  1450. brcc t0h_int_rcp_limit_middle_ramp
  1451. ldi I_Temp1, 1 ; Slow initial spoolup
  1452. ldi XL, 3
  1453. sts Spoolup_Limit_Skip, XL
  1454. rjmp t0h_int_rcp_set_limit
  1455. t0h_int_rcp_limit_middle_ramp:
  1456. cpi I_Temp2, (15*MAIN_SPOOLUP_TIME) ; Faster spoolup until "150"*32ms
  1457. brcc t0h_int_rcp_set_limit
  1458. ldi I_Temp1, 1 ; Faster middle spoolup
  1459. sts Spoolup_Limit_Skip, I_Temp1
  1460. t0h_int_rcp_set_limit:
  1461. ; Do not increment spoolup limit if higher pwm is not requested, unless governor is active
  1462. lds I_Temp6, Pwm_Limit_Spoolup ; Load pwm limit spoolup
  1463. lds I_Temp5, Current_Pwm ; Load current pwm
  1464. cp I_Temp6, I_Temp5
  1465. brcs t0h_int_rcp_inc_limit ; If Current_Pwm is larger than Pwm_Limit_Spoolup - branch
  1466. lds XL, Pgm_Gov_Mode ; Governor mode?
  1467. cpi XL, 4
  1468. breq t0h_int_rcp_bailout_arm ; No - branch
  1469. sbrc Flags0, GOV_ACTIVE ; Is governor active?
  1470. rjmp t0h_int_rcp_inc_limit ; Yes - branch
  1471. sts Pwm_Limit_Spoolup, I_Temp5 ; Set limit to what current pwm is
  1472. inc I_Temp2 ; Check if spoolup limit count is 255
  1473. breq PC+4 ; If it is, then this is a "bailout" ramp
  1474. ldi XL, (3*MAIN_SPOOLUP_TIME) ; Stay in an early part of the spoolup sequence (unless "bailout" ramp)
  1475. sts Spoolup_Limit_Cnt, XL
  1476. ldi XL, 1 ; Set skip count
  1477. sts Spoolup_Limit_Skip, XL
  1478. ldi XL, 60 ; Set governor requested speed to ensure that it requests higher speed
  1479. sts Governor_Req_Pwm, XL
  1480. ; 20=Fail on jerk when governor activates
  1481. ; 30=Ok
  1482. ; 100=Fail on small governor settling overshoot on low headspeeds
  1483. ; 200=Fail on governor settling overshoot
  1484. rjmp t0h_int_rcp_exit ; Exit
  1485. t0h_int_rcp_inc_limit:
  1486. lds XL, Pwm_Limit_Spoolup ; Increment spoolup pwm
  1487. add XL, I_Temp1
  1488. brcc t0h_int_rcp_no_limit ; If below 255 - branch
  1489. ldi I_Temp2, 0xFF
  1490. sts Pwm_Limit_Spoolup, I_Temp2
  1491. rjmp t0h_int_rcp_bailout_arm
  1492. t0h_int_rcp_no_limit:
  1493. sts Pwm_Limit_Spoolup, XL
  1494. t0h_int_rcp_bailout_arm:
  1495. lds XL, Pwm_Limit_Spoolup
  1496. cpi XL, 0xFF
  1497. brne t0h_int_rcp_exit
  1498. ldi XL, 0xFF
  1499. sts Auto_Bailout_Armed, XL ; Arm bailout
  1500. sts Spoolup_Limit_Cnt, XL
  1501. .ENDIF
  1502. .IF MODE == 2 ; Multi
  1503. lds XL, Pwm_Limit_Spoolup ; Increment spoolup pwm, for a 0.8 seconds spoolup
  1504. subi XL, 0xF6 ; Subtract -10
  1505. brcs t0h_int_rcp_no_limit ; If below 255 - branch
  1506. ldi I_Temp2, 0xFF
  1507. sts Pwm_Limit_Spoolup, I_Temp2
  1508. rjmp t0h_int_rcp_exit
  1509. t0h_int_rcp_no_limit:
  1510. sts Pwm_Limit_Spoolup, XL
  1511. .ENDIF
  1512. t0h_int_rcp_exit:
  1513. cli ; Disable interrupts
  1514. T0_Int_Enable XL ; Enable timer0 interrupts
  1515. sbrs Flags2, RCP_INT_NESTED_ENABLED; Restore rcp interrupt state
  1516. rjmp t0h_int_pwm_ret
  1517. Rcp_Int_Enable XL
  1518. t0h_int_pwm_ret:
  1519. out SREG, I_Sreg
  1520. reti
  1521. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  1522. ;
  1523. ; RC pulse interrupt routine
  1524. ;
  1525. ; No assumptions
  1526. ; Can come from int0 or icp
  1527. ;
  1528. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  1529. rcp_int: ; Used for RC pulse timing
  1530. in I_Sreg, SREG
  1531. ; Get the timer counter values
  1532. Get_Rcp_Capture_Values I_Temp1, I_Temp2
  1533. ; Disable RCP interrupts
  1534. cbr Flags2, (1<<RCP_INT_NESTED_ENABLED) ; Set flag default to disabled
  1535. Get_Rcp_Int_Enable_State XL ; Get rcp interrupt state
  1536. cpse XL, Zero
  1537. sbr Flags2, (1<<RCP_INT_NESTED_ENABLED) ; Set flag to enabled
  1538. Rcp_Int_Disable XL ; Disable rcp interrupts
  1539. T0_Int_Disable XL ; Disable timer0 interrupts
  1540. sei ; Enable interrupts
  1541. ; Check which edge it is
  1542. sbrc Flags2, RCP_EDGE_NO ; Is it a first edge trig?
  1543. rjmp rcp_int_second_meas_pwm_freq ; No - branch to second
  1544. Rcp_Int_Second XL ; Yes - set second edge trig
  1545. sbr Flags2, (1<<RCP_EDGE_NO) ; Set second edge flag
  1546. ; Read RC signal level
  1547. Read_Rcp_Int XL
  1548. ; Test RC signal level
  1549. sbrs XL, Rcp_In ; Is it high?
  1550. rjmp rcp_int_fail_minimum ; No - jump to fail minimum
  1551. ; RC pulse was high, store RC pulse start timestamp
  1552. sts Rcp_Prev_Edge_L, I_Temp1
  1553. sts Rcp_Prev_Edge_H, I_Temp2
  1554. rjmp rcp_int_exit ; Exit
  1555. rcp_int_fail_minimum:
  1556. ; Prepare for next interrupt
  1557. Rcp_Int_First XL ; Set interrupt trig to first again
  1558. Rcp_Clear_Int_Flag XL ; Clear interrupt flag
  1559. cbr Flags2, (1<<RCP_EDGE_NO) ; Set first edge flag
  1560. mov XL, Flags3 ; Check pwm frequency flags
  1561. andi XL, ((1<<RCP_PWM_FREQ_1KHZ)+(1<<RCP_PWM_FREQ_2KHZ)+(1<<RCP_PWM_FREQ_4KHZ)+(1<<RCP_PWM_FREQ_8KHZ)+(1<<RCP_PWM_FREQ_12KHZ))
  1562. brne PC+2
  1563. rjmp rcp_int_set_timeout ; If no flag is set (PPM) - ignore trig as noise
  1564. ldi I_Temp1, RCP_MIN ; Set RC pulse value to minimum
  1565. Read_Rcp_Int XL ; Test RC signal level again
  1566. sbrc XL, Rcp_In ; Is it high?
  1567. rjmp rcp_int_set_timeout ; Yes - set new timeout and exit
  1568. sts New_Rcp, I_Temp1 ; Store new pulse length
  1569. rjmp rcp_int_limited ; Set new RC pulse, new timeout and exit
  1570. rcp_int_second_meas_pwm_freq:
  1571. ; Prepare for next interrupt
  1572. Rcp_Int_First XL ; Set first edge trig
  1573. cbr Flags2, (1<<RCP_EDGE_NO) ; Set first edge flag
  1574. ; Check if pwm frequency shall be measured
  1575. sbrs Flags0, RCP_MEAS_PWM_FREQ ; Is measure RCP pwm frequency flag set?
  1576. rjmp rcp_int_fall ; No - skip measurements
  1577. ; Set second edge trig only during pwm frequency measurement
  1578. Rcp_Int_Second XL ; Set second edge trig
  1579. Rcp_Clear_Int_Flag XL ; Clear interrupt flag
  1580. sbr Flags2, (1<<RCP_EDGE_NO) ; Set second edge flag
  1581. ; Store edge data to RAM
  1582. sts Rcp_Edge_L, I_Temp1
  1583. sts Rcp_Edge_H, I_Temp2
  1584. ; Calculate pwm frequency
  1585. lds I_Temp3, Rcp_PrePrev_Edge_L
  1586. sub I_Temp1, I_Temp3
  1587. lds I_Temp4, Rcp_PrePrev_Edge_H
  1588. sbc I_Temp2, I_Temp4
  1589. clr I_Temp4
  1590. ldi XL, 250 ; Set default period tolerance requirement
  1591. mov I_Temp3, XL
  1592. ; Check if pwm frequency is 12kHz
  1593. cpi I_Temp1, low(200) ; If below 100us, 12kHz pwm is assumed
  1594. ldi XL, high(200)
  1595. cpc I_Temp2, XL
  1596. brcc rcp_int_check_8kHz
  1597. ldi XL, (1<<RCP_PWM_FREQ_12KHZ)
  1598. mov I_Temp4, XL
  1599. ldi XL, 10 ; Set period tolerance requirement
  1600. mov I_Temp3, XL
  1601. rjmp rcp_int_restore_edge
  1602. rcp_int_check_8kHz:
  1603. ; Check if pwm frequency is 8kHz
  1604. cpi I_Temp1, low(360) ; If below 180us, 8kHz pwm is assumed
  1605. ldi XL, high(360)
  1606. cpc I_Temp2, XL
  1607. brcc rcp_int_check_4kHz
  1608. ldi XL, (1<<RCP_PWM_FREQ_8KHZ)
  1609. mov I_Temp4, XL
  1610. ldi XL, 15 ; Set period tolerance requirement
  1611. mov I_Temp3, XL
  1612. rjmp rcp_int_restore_edge
  1613. rcp_int_check_4kHz:
  1614. ; Check if pwm frequency is 4kHz
  1615. cpi I_Temp1, low(720) ; If below 360us, 4kHz pwm is assumed
  1616. ldi XL, high(720)
  1617. cpc I_Temp2, XL
  1618. brcc rcp_int_check_2kHz
  1619. ldi XL, (1<<RCP_PWM_FREQ_4KHZ)
  1620. mov I_Temp4, XL
  1621. ldi XL, 30 ; Set period tolerance requirement
  1622. mov I_Temp3, XL
  1623. rjmp rcp_int_restore_edge
  1624. rcp_int_check_2kHz:
  1625. ; Check if pwm frequency is 2kHz
  1626. cpi I_Temp1, low(1440) ; If below 720us, 2kHz pwm is assumed
  1627. ldi XL, high(1440)
  1628. cpc I_Temp2, XL
  1629. brcc rcp_int_check_1kHz
  1630. ldi XL, (1<<RCP_PWM_FREQ_2KHZ)
  1631. mov I_Temp4, XL
  1632. ldi XL, 60 ; Set period tolerance requirement
  1633. mov I_Temp3, XL
  1634. rjmp rcp_int_restore_edge
  1635. rcp_int_check_1kHz:
  1636. ; Check if pwm frequency is 1kHz
  1637. cpi I_Temp1, low(2200) ; If below 1100us, 1kHz pwm is assumed
  1638. ldi XL, high(2200)
  1639. cpc I_Temp2, XL
  1640. brcc rcp_int_restore_edge
  1641. ldi XL, (1<<RCP_PWM_FREQ_1KHZ)
  1642. mov I_Temp4, XL
  1643. ldi XL, 120 ; Set period tolerance requirement
  1644. mov I_Temp3, XL
  1645. rcp_int_restore_edge:
  1646. ; Calculate difference between this period and previous period
  1647. mov I_Temp5, I_Temp1
  1648. lds I_Temp7, Rcp_Prev_Period_L
  1649. sub I_Temp5, I_Temp7
  1650. mov I_Temp6, I_Temp2
  1651. lds I_Temp8, Rcp_Prev_Period_H
  1652. sbc I_Temp6, I_Temp8
  1653. ; Make positive
  1654. tst I_Temp6
  1655. brpl rcp_int_check_diff
  1656. ldi XL, 0xFF ; Change sign - invert and subtract minus one
  1657. com I_Temp5
  1658. com I_Temp6
  1659. sub I_Temp5, XL
  1660. sbc I_Temp6, XL
  1661. rcp_int_check_diff:
  1662. ; Check difference
  1663. sts Rcp_Period_Diff_Accepted, Zero ; Set not accepted as default
  1664. tst I_Temp6 ; Check if high byte is zero
  1665. brne rcp_int_store_data
  1666. cp I_Temp5, I_Temp3 ; Check difference
  1667. brcc rcp_int_store_data
  1668. ldi XL, 1 ; Set accepted
  1669. sts Rcp_Period_Diff_Accepted, XL
  1670. rcp_int_store_data:
  1671. ; Store previous period
  1672. sts Rcp_Prev_Period_L, I_Temp1
  1673. sts Rcp_Prev_Period_H, I_Temp2
  1674. ; Restore edge data from RAM
  1675. lds I_Temp1, Rcp_Edge_L
  1676. lds I_Temp2, Rcp_Edge_H
  1677. ; Store pre previous edge
  1678. sts Rcp_PrePrev_Edge_L, I_Temp1
  1679. sts Rcp_PrePrev_Edge_H, I_Temp2
  1680. rcp_int_fall:
  1681. ; RC pulse edge was second, calculate new pulse length
  1682. lds I_Temp7, Rcp_Prev_Edge_L
  1683. sub I_Temp1, I_Temp7
  1684. lds I_Temp8, Rcp_Prev_Edge_H
  1685. sbc I_Temp2, I_Temp8
  1686. sbrc Flags3, RCP_PWM_FREQ_12KHZ ; Is RC input pwm frequency 12kHz?
  1687. rjmp rcp_int_pwm_divide_done ; Yes - branch forward
  1688. sbrc Flags3, RCP_PWM_FREQ_8KHZ ; Is RC input pwm frequency 8kHz?
  1689. rjmp rcp_int_pwm_divide_done ; Yes - branch forward
  1690. sbrc Flags3, RCP_PWM_FREQ_4KHZ ; Is RC input pwm frequency 4kHz?
  1691. rjmp rcp_int_pwm_divide ; Yes - branch forward
  1692. lsr I_Temp2 ; No - 2kHz. Divide by 2
  1693. ror I_Temp1
  1694. sbrc Flags3, RCP_PWM_FREQ_2KHZ ; Is RC input pwm frequency 2kHz?
  1695. rjmp rcp_int_pwm_divide ; Yes - branch forward
  1696. lsr I_Temp2 ; No - 1kHz. Divide by 2 again
  1697. ror I_Temp1
  1698. sbrc Flags3, RCP_PWM_FREQ_1KHZ ; Is RC input pwm frequency 1kHz?
  1699. rjmp rcp_int_pwm_divide ; Yes - branch forward
  1700. mov I_Temp6, I_Temp2 ; No - PPM. Divide by 2 (to bring range to 256) and move to I_Temp5/6
  1701. mov I_Temp5, I_Temp1
  1702. lsr I_Temp6
  1703. ror I_Temp5
  1704. ; Skip range limitation if pwm frequency measurement
  1705. sbrc Flags0, RCP_MEAS_PWM_FREQ
  1706. rjmp rcp_int_ppm_check_full_range
  1707. ; Check if 2160us or above (in order to ignore false pulses)
  1708. mov XL, I_Temp5 ; Is pulse 2160us or higher?
  1709. subi XL, 28
  1710. mov XL, I_Temp6
  1711. sbci XL, 2
  1712. brcs PC+2
  1713. rjmp rcp_int_set_timeout ; Yes - ignore pulse
  1714. ; Check if below 800us (in order to ignore false pulses)
  1715. tst I_Temp6
  1716. brne rcp_int_ppm_check_full_range
  1717. mov XL, I_Temp5 ; Is pulse below 800us?
  1718. subi XL, 200
  1719. brcc rcp_int_ppm_check_full_range ; No - branch
  1720. rjmp rcp_int_set_timeout ; Yes - ignore pulse
  1721. rcp_int_ppm_check_full_range:
  1722. ; Calculate "1000us" plus throttle minimum
  1723. ldi XL, 0 ; Set 1000us as default minimum
  1724. mov I_Temp7, XL
  1725. sbrc Flags3, FULL_THROTTLE_RANGE ; Check if full range is chosen
  1726. rjmp rcp_int_ppm_calculate ; Yes - branch
  1727. lds I_Temp7, Pgm_Ppm_Min_Throttle ; Min throttle value is in 4us units
  1728. .IF MODE >= 1 ; Tail or multi
  1729. lds XL, Pgm_Direction ; Check if bidirectional operation
  1730. cpi XL, 3
  1731. brne PC+3 ; No - branch
  1732. lds I_Temp7, Pgm_Ppm_Center_Throttle ; Center throttle value is in 4us units
  1733. .ENDIF
  1734. rcp_int_ppm_calculate:
  1735. ldi XL, 250 ; Add 1000us to minimum
  1736. add I_Temp7, XL
  1737. mov I_Temp8, Zero
  1738. adc I_Temp8, Zero
  1739. sub I_Temp5, I_Temp7 ; Subtract minimum
  1740. sbc I_Temp6, I_Temp8
  1741. in I_Temp1, SREG
  1742. andi I_Temp1, (1<<SREG_C)
  1743. .IF MODE >= 1 ; Tail or multi
  1744. lds XL, Pgm_Direction ; Check if bidirectional operation
  1745. cpi XL, 3
  1746. brne rcp_int_ppm_bidir_dir_set ; No - branch
  1747. tst I_Temp1
  1748. breq rcp_int_ppm_bidir_fwd ; If result is positive - branch
  1749. rcp_int_ppm_bidir_rev:
  1750. sbrc Flags3, PGM_DIR_REV
  1751. rjmp rcp_int_ppm_bidir_dir_set ; If same direction - branch
  1752. cli ; Direction change, turn off all fets
  1753. sbr Flags3, (1<<PGM_DIR_REV)
  1754. rjmp rcp_int_ppm_bidir_dir_change
  1755. rcp_int_ppm_bidir_fwd:
  1756. sbrs Flags3, PGM_DIR_REV
  1757. rjmp rcp_int_ppm_bidir_dir_set ; If same direction - branch
  1758. cli ; Direction change, turn off all fets
  1759. cbr Flags3, (1<<PGM_DIR_REV)
  1760. rcp_int_ppm_bidir_dir_change:
  1761. All_nFETs_Off
  1762. All_pFETs_Off
  1763. sei
  1764. rcp_int_ppm_bidir_dir_set:
  1765. .ENDIF
  1766. tst I_Temp1
  1767. breq rcp_int_ppm_neg_checked ; If result is positive - branch
  1768. .IF MODE >= 1 ; Tail or multi
  1769. lds XL, Pgm_Direction ; Check if bidirectional operation
  1770. cpi XL, 3
  1771. brne rcp_int_ppm_unidir_neg ; No - branch
  1772. ldi XL, 0xFF ; Change sign - invert and subtract minus one
  1773. com I_Temp5
  1774. com I_Temp6
  1775. sub I_Temp5, XL
  1776. sbc I_Temp6, XL
  1777. rjmp rcp_int_ppm_neg_checked
  1778. rcp_int_ppm_unidir_neg:
  1779. .ENDIF
  1780. ldi I_Temp1, RCP_MIN ; Yes - set to minimum
  1781. ldi I_Temp2, 0
  1782. rjmp rcp_int_pwm_divide_done
  1783. rcp_int_ppm_neg_checked:
  1784. .IF MODE >= 1 ; Tail or multi
  1785. lds XL, Pgm_Direction ; Check if bidirectional operation
  1786. cpi XL, 3
  1787. brne rcp_int_ppm_bidir_done ; No - branch
  1788. lsl I_Temp5 ; Multiply value by 2
  1789. rol I_Temp6
  1790. ldi XL, 5 ; Subtract deadband
  1791. sub I_Temp5, XL
  1792. sbc I_Temp6, Zero
  1793. brcc rcp_int_ppm_bidir_done
  1794. ldi XL, RCP_MIN
  1795. mov I_Temp5, XL
  1796. mov I_Temp6, Zero
  1797. rcp_int_ppm_bidir_done:
  1798. .ENDIF
  1799. ldi XL, RCP_MAX ; Check that RC pulse is within legal range (max 255)
  1800. cp I_Temp5, XL
  1801. cpc I_Temp6, Zero
  1802. brcs rcp_int_ppm_max_checked
  1803. ldi I_Temp1, RCP_MAX
  1804. ldi I_Temp2, 0
  1805. rjmp rcp_int_pwm_divide_done
  1806. rcp_int_ppm_max_checked:
  1807. lds I_Temp8, Ppm_Throttle_Gain ; Multiply throttle value by gain
  1808. mul I_Temp5, I_Temp8
  1809. mov I_Temp1, Mul_Res_H ; Transfer result
  1810. lsl Mul_Res_L ; Multiply result by 2 (unity gain is 128)
  1811. rol I_Temp1
  1812. ldi I_Temp2, 0
  1813. brcs rcp_int_ppm_limit_after_mult
  1814. rjmp rcp_int_limited
  1815. rcp_int_ppm_limit_after_mult:
  1816. ldi I_Temp1, RCP_MAX
  1817. ldi I_Temp2, 0
  1818. rjmp rcp_int_limited
  1819. rcp_int_pwm_divide:
  1820. lsr I_Temp2 ; Divide by 2
  1821. ror I_Temp1
  1822. rcp_int_pwm_divide_done:
  1823. sbrs Flags3, RCP_PWM_FREQ_12KHZ ; Is RC input pwm frequency 12kHz?
  1824. rjmp rcp_int_check_legal_range
  1825. tst I_Temp2 ; Yes - check that value is not more than 255
  1826. breq PC+2
  1827. ldi I_Temp1, RCP_MAX
  1828. mov XL, I_Temp1 ; Multiply by 1.5
  1829. lsr XL
  1830. add I_Temp1, XL
  1831. adc I_Temp2, Zero
  1832. rcp_int_check_legal_range:
  1833. ; Check that RC pulse is within legal range
  1834. cpi I_Temp1, RCP_MAX
  1835. cpc I_Temp2, Zero
  1836. brcs rcp_int_limited
  1837. ldi I_Temp1, RCP_MAX
  1838. rcp_int_limited:
  1839. ; RC pulse value accepted
  1840. sts New_Rcp, I_Temp1 ; Store new pulse length
  1841. sbr Flags2, (1<<RCP_UPDATED) ; Set updated flag
  1842. sbrs Flags0, RCP_MEAS_PWM_FREQ ; Is measure RCP pwm frequency flag set?
  1843. rjmp rcp_int_set_timeout ; No - skip measurements
  1844. ldi XL, ((1<<RCP_PWM_FREQ_1KHZ)+(1<<RCP_PWM_FREQ_2KHZ)+(1<<RCP_PWM_FREQ_4KHZ)+(1<<RCP_PWM_FREQ_8KHZ)+(1<<RCP_PWM_FREQ_12KHZ))
  1845. com XL
  1846. and XL, Flags3 ; Clear all pwm frequency flags
  1847. or XL, I_Temp4 ; Store pwm frequency value in flags
  1848. mov Flags3, XL
  1849. rcp_int_set_timeout:
  1850. ldi XL, RCP_TIMEOUT ; Set timeout count to start value
  1851. sts Rcp_Timeout_Cnt, XL
  1852. mov XL, Flags3 ; Check pwm frequency flags
  1853. andi XL, ((1<<RCP_PWM_FREQ_1KHZ)+(1<<RCP_PWM_FREQ_2KHZ)+(1<<RCP_PWM_FREQ_4KHZ)+(1<<RCP_PWM_FREQ_8KHZ)+(1<<RCP_PWM_FREQ_12KHZ))
  1854. brne rcp_int_ppm_timeout_set ; If a flag is set (PWM) - branch
  1855. ldi XL, RCP_TIMEOUT_PPM ; No flag set means PPM. Set timeout count
  1856. sts Rcp_Timeout_Cnt, XL
  1857. rcp_int_ppm_timeout_set:
  1858. sbrc Flags0, RCP_MEAS_PWM_FREQ ; Is measure RCP pwm frequency flag set?
  1859. rjmp rcp_int_exit ; Yes - exit
  1860. mov XL, Flags3 ; Check pwm frequency flags
  1861. andi XL, ((1<<RCP_PWM_FREQ_1KHZ)+(1<<RCP_PWM_FREQ_2KHZ)+(1<<RCP_PWM_FREQ_4KHZ)+(1<<RCP_PWM_FREQ_8KHZ)+(1<<RCP_PWM_FREQ_12KHZ))
  1862. breq rcp_int_exit ; If no flag is set (PPM) - branch
  1863. cbr Flags2, (1<<RCP_INT_NESTED_ENABLED) ; Set flag to disabled
  1864. rcp_int_exit: ; Exit interrupt routine
  1865. ldi XL, RCP_SKIP_RATE ; Load number of skips
  1866. sts Rcp_Skip_Cnt, XL
  1867. mov XL, Flags3 ; Check pwm frequency flags
  1868. andi XL, ((1<<RCP_PWM_FREQ_1KHZ)+(1<<RCP_PWM_FREQ_2KHZ)+(1<<RCP_PWM_FREQ_4KHZ)+(1<<RCP_PWM_FREQ_8KHZ)+(1<<RCP_PWM_FREQ_12KHZ))
  1869. brne PC+4 ; If a flag is set (PWM) - branch
  1870. ldi XL, 10 ; Load number of skips
  1871. sts Rcp_Skip_Cnt, XL
  1872. cli ; Disable interrupts
  1873. T0_Int_Enable XL ; Enable timer0 interrupts
  1874. sbrs Flags2, RCP_INT_NESTED_ENABLED; Restore rcp interrupt state
  1875. rjmp rcp_int_ret
  1876. Rcp_Int_Enable XL
  1877. rcp_int_ret:
  1878. out SREG, I_Sreg
  1879. reti
  1880. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  1881. ;
  1882. ; Wait xms ~(x*4*250) (Different entry points)
  1883. ;
  1884. ; No assumptions
  1885. ;
  1886. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  1887. wait1ms:
  1888. ldi Temp2, 1
  1889. rjmp waitxms_o
  1890. wait3ms:
  1891. ldi Temp2, 3
  1892. rjmp waitxms_o
  1893. wait10ms:
  1894. ldi Temp2, 10
  1895. rjmp waitxms_o
  1896. wait30ms:
  1897. ldi Temp2, 30
  1898. rjmp waitxms_o
  1899. wait100ms:
  1900. ldi Temp2, 100
  1901. rjmp waitxms_o
  1902. wait200ms:
  1903. ldi Temp2, 200
  1904. rjmp waitxms_o
  1905. waitxms_o: ; Outer loop
  1906. ldi Temp1, 21
  1907. .IF CLK_8M == 1
  1908. ldi Temp1, 10
  1909. .ENDIF
  1910. waitxms_m: ; Middle loop
  1911. clr XH
  1912. dec XH
  1913. brne PC-1 ; Inner loop
  1914. dec Temp1
  1915. brne waitxms_m
  1916. dec Temp2
  1917. brne waitxms_o
  1918. ret
  1919. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  1920. ;
  1921. ; Beeper routines (4 different entry points)
  1922. ;
  1923. ; No assumptions
  1924. ;
  1925. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  1926. beep_f1: ; Entry point 1, load beeper frequency 1 settings
  1927. ldi Temp3, 58 ; Off wait loop length
  1928. ldi Temp4, 120 ; Number of beep pulses
  1929. rjmp beep_init
  1930. beep_f2: ; Entry point 2, load beeper frequency 2 settings
  1931. ldi Temp3, 48
  1932. ldi Temp4, 140
  1933. rjmp beep_init
  1934. beep_f3: ; Entry point 3, load beeper frequency 3 settings
  1935. ldi Temp3, 42
  1936. ldi Temp4, 180
  1937. rjmp beep_init
  1938. beep_f4: ; Entry point 4, load beeper frequency 4 settings
  1939. ldi Temp3, 37
  1940. ldi Temp4, 200
  1941. rjmp beep_init
  1942. beep_init:
  1943. .IF CLK_8M == 1
  1944. subi Temp3, 28
  1945. .ENDIF
  1946. beep: ; Beep loop start
  1947. mov Temp5, Current_Pwm_Limited ; Store value
  1948. ldi XH, 1 ; Set to a nonzero value
  1949. mov Current_Pwm_Limited, XH
  1950. ldi Temp2, 2 ; Must be an even number (or direction will change)
  1951. beep_onoff:
  1952. sbrc Flags3, PGM_DIR_REV ; Toggle between using A fet and C fet
  1953. cbr Flags3, (1<<PGM_DIR_REV)
  1954. sbrs Flags3, PGM_DIR_REV ; Toggle between using A fet and C fet
  1955. sbr Flags3, (1<<PGM_DIR_REV)
  1956. clr XH
  1957. BpFET_off ; BpFET off
  1958. dec XH ; Allow some time after pfet is turned off
  1959. brne PC-1
  1960. BnFET_on ; BnFET on (in order to charge the driver of the BpFET)
  1961. dec XH ; Let the nfet be turned on a while
  1962. brne PC-1
  1963. BnFET_off ; BnFET off again
  1964. dec XH ; Allow some time after nfet is turned off
  1965. brne PC-1
  1966. BpFET_on ; BpFET on
  1967. dec XH ; Allow some time after pfet is turned on
  1968. brne PC-1
  1969. ; Turn on nfet
  1970. AnFET_on ; AnFET on
  1971. lds XH, Beep_Strength
  1972. dec XH
  1973. brne PC-1
  1974. ; Turn off nfet
  1975. AnFET_off ; AnFET off
  1976. ldi XH, 135 ; 25�s off
  1977. dec XH
  1978. brne PC-1
  1979. dec Temp2
  1980. brne beep_onoff
  1981. ; Copy variable
  1982. mov Temp1, Temp3
  1983. beep_off: ; Fets off loop
  1984. mov XH, Temp3
  1985. dec XH
  1986. brne PC-1
  1987. dec Temp1
  1988. brne beep_off
  1989. dec Temp4
  1990. brne beep
  1991. BpFET_off ; BpFET off
  1992. mov Current_Pwm_Limited, Temp5 ; Restore value
  1993. ret
  1994. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  1995. ;
  1996. ; Division 16bit unsigned by 16bit unsigned
  1997. ;
  1998. ; Dividend shall be in Temp2/Temp1, divisor in Temp4/Temp3
  1999. ; Result will be in Temp2/Temp1
  2000. ;
  2001. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  2002. div_u16_by_u16:
  2003. mov Temp5, Zero
  2004. mov Temp6, Zero
  2005. ldi XH, 0
  2006. clc
  2007. div_u16_by_u16_div1:
  2008. inc XH ; Increment counter for each left shift
  2009. rol Temp3 ; Shift left the divisor
  2010. rol Temp4
  2011. brcc div_u16_by_u16_div1 ; Repeat until carry flag is set from high-byte
  2012. div_u16_by_u16_div2:
  2013. ror Temp4 ; Shift right the divisor
  2014. ror Temp3
  2015. clc
  2016. mov Temp8, Temp2 ; Make a safe copy of the dividend
  2017. mov Temp7, Temp1
  2018. sbc Temp1, Temp3 ; Dividend - shifted divisor = result bit (no factor, only 0 or 1)
  2019. sbc Temp2, Temp4 ; Subtract high-byte of divisor (all together 16-bit substraction)
  2020. brcc div_u16_by_u16_div3 ; If carry flag is NOT set, result is 1
  2021. mov Temp2, Temp8 ; Otherwise result is 0, save copy of divisor to undo subtraction
  2022. mov Temp1, Temp7
  2023. div_u16_by_u16_div3:
  2024. brcc PC+3 ; Invert carry, so it can be directly copied into result
  2025. clc
  2026. rjmp PC+2
  2027. sec
  2028. rol Temp5 ; Shift carry flag into temporary result
  2029. rol Temp6
  2030. dec XH
  2031. brne div_u16_by_u16_div2 ;Now count backwards and repeat until "B" is zero
  2032. mov Temp2, Temp6 ; Move result to Temp2/Temp1
  2033. mov Temp1, Temp5
  2034. ret
  2035. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  2036. ;
  2037. ; Multiplication 16bit signed by 8bit unsigned
  2038. ;
  2039. ; Multiplicand shall be in Temp2/Temp1, multiplicator in Temp3
  2040. ; Result will be in Temp2/Temp1. Result will divided by 16
  2041. ;
  2042. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  2043. mult_s16_by_u8_div_16:
  2044. mov Temp4, Zero ; Set default sign in Temp4
  2045. tst Temp2 ; Test sign
  2046. brpl mult_s16_by_u8_positive
  2047. dec Temp4 ; Set sign to 0xFF
  2048. com Temp1 ; Change sign - invert and subtract minus one
  2049. com Temp2
  2050. sub Temp1, Temp4
  2051. sbc Temp2, Temp4
  2052. mult_s16_by_u8_positive:
  2053. cli ; Disable interrupts in order to avoid interference with mul ops in interrupt routines
  2054. mul Temp1, Temp3 ; Multiply LSB with multiplicator
  2055. mov Temp6, Mul_Res_H ; Place MSB in Temp6
  2056. mov Temp1, Mul_Res_L ; Place LSB in Temp1 (result)
  2057. mul Temp2, Temp3 ; Multiply MSB with multiplicator
  2058. mov Temp8, Mul_Res_H ; Place in Temp8/7
  2059. mov Temp7, Mul_Res_L
  2060. sei
  2061. add Temp6, Temp7 ; Add up into Temp3/2
  2062. mov Temp2, Temp6
  2063. adc Temp8, Zero
  2064. mov Temp3, Temp8
  2065. ldi XH, 4
  2066. mov Temp5, XH ; Set number of divisions
  2067. mult_s16_by_u8_div_loop:
  2068. lsr Temp3 ; Rotate right
  2069. ror Temp2
  2070. ror Temp1
  2071. dec Temp5
  2072. brne mult_s16_by_u8_div_loop
  2073. tst Temp4 ; Test sign
  2074. breq mult_s16_by_u8_exit
  2075. com Temp1 ; Change sign - invert and subtract minus one
  2076. com Temp2
  2077. sub Temp1, Temp4
  2078. sbc Temp2, Temp4
  2079. mult_s16_by_u8_exit:
  2080. ret
  2081. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  2082. ;
  2083. ; Calculate governor routines
  2084. ;
  2085. ; No assumptions
  2086. ;
  2087. ; Governs headspeed based upon the Comm_Period4x variable and pwm
  2088. ; The governor task is split into several routines in order to distribute processing time
  2089. ;
  2090. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  2091. ; First governor routine - calculate governor target
  2092. .IF MODE == 0 ; Main
  2093. calc_governor_target:
  2094. lds Temp1, Pgm_Gov_Mode ; Governor mode?
  2095. cpi Temp1, 4
  2096. brne PC+2
  2097. rjmp calc_governor_target_exit ; No
  2098. governor_speed_check:
  2099. ; Stop governor for stop RC pulse
  2100. lds XH, New_Rcp ; Check RC pulse against stop value
  2101. subi XH, (RCP_MAX/10) ; Is pulse below stop value?
  2102. brcs governor_deactivate ; Yes - deactivate
  2103. mov XH, Flags1
  2104. andi XH, ((1<<STARTUP_PHASE)+(1<<INITIAL_RUN_PHASE))
  2105. brne governor_deactivate ; Deactivate if any startup phase set
  2106. ; Skip speed check if governor is already active
  2107. sbrc Flags0, GOV_ACTIVE ; Is governor active?
  2108. rjmp governor_target_calc
  2109. ; Check speed (do not run governor for low speeds)
  2110. ldi Temp1, 5 ; Default high range activation limit value (~62500 eRPM)
  2111. lds Temp8, Pgm_Gov_Range
  2112. mov XH, Temp8 ; Check if high range (Temp8 has Pgm_Gov_Range)
  2113. dec XH
  2114. breq governor_act_lim_set ; If high range - branch
  2115. ldi Temp1, 10 ; Middle range activation limit value (~31250 eRPM)
  2116. dec XH
  2117. breq governor_act_lim_set ; If middle range - branch
  2118. ldi Temp1, 18 ; Low range activation limit value (~17400 eRPM)
  2119. governor_act_lim_set:
  2120. lds XH, Comm_Period4x_H
  2121. sub XH, Temp1
  2122. brcs governor_activate ; If speed above min limit - run governor
  2123. governor_deactivate:
  2124. sbrs Flags0, GOV_ACTIVE ; Is governor active?
  2125. rjmp governor_first_deactivate_done; This code is executed continuously. Only execute the code below the first time
  2126. lds XH, Pwm_Spoolup_Beg
  2127. sts Pwm_Limit_Spoolup, XH
  2128. ldi XH, 255
  2129. sts Spoolup_Limit_Cnt, XH
  2130. ldi XH, 1
  2131. sts Spoolup_Limit_Skip, XH
  2132. governor_first_deactivate_done:
  2133. lds XH, Requested_Pwm ; Set current pwm to requested
  2134. sts Current_Pwm, XH
  2135. sts Gov_Target_L, Zero ; Set target to zero
  2136. sts Gov_Target_H, Zero
  2137. sts Gov_Integral_L, Zero ; Set integral to zero
  2138. sts Gov_Integral_H, Zero
  2139. sts Gov_Integral_X, Zero
  2140. cbr Flags0, (1<<GOV_ACTIVE)
  2141. rjmp calc_governor_target_exit
  2142. governor_activate:
  2143. sbr Flags0, (1<<GOV_ACTIVE)
  2144. governor_target_calc:
  2145. ; Governor calculations
  2146. lds Temp8, Pgm_Gov_Range
  2147. mov XH, Temp8 ; Check high, middle or low range
  2148. dec XH
  2149. brne calc_governor_target_middle
  2150. lds XH, Governor_Req_Pwm ; Load governor requested pwm
  2151. com XH ; Calculate 255-pwm (invert pwm)
  2152. ; Calculate comm period target (1 + 2*((255-Requested_Pwm)/256) - 0.25)
  2153. rol XH ; Msb to carry
  2154. rol XH ; To bit0
  2155. mov Temp2, XH ; Now 1 lsb is valid for H
  2156. ror XH
  2157. mov Temp1, XH ; Now 7 msbs are valid for L
  2158. mov XH, Temp2
  2159. andi XH, 0x01 ; Calculate H byte
  2160. inc XH ; Add 1
  2161. mov Temp2, XH
  2162. mov XH, Temp1
  2163. andi XH, 0xFE ; Calculate L byte
  2164. rjmp calc_governor_subtract_025
  2165. calc_governor_target_middle:
  2166. mov XH, Temp8 ; Check middle or low range (Temp8 has Pgm_Gov_Range)
  2167. dec XH
  2168. dec XH
  2169. brne calc_governor_target_low
  2170. lds XH, Governor_Req_Pwm ; Load governor requested pwm
  2171. com XH ; Calculate 255-pwm (invert pwm)
  2172. ; Calculate comm period target (1 + 4*((255-Requested_Pwm)/256))
  2173. rol XH ; Msb to carry
  2174. rol XH ; To bit0
  2175. rol XH ; To bit1
  2176. mov Temp2, XH ; Now 2 lsbs are valid for H
  2177. ror XH
  2178. mov Temp1, XH ; Now 6 msbs are valid for L
  2179. mov XH, Temp2
  2180. andi XH, 0x03 ; Calculate H byte
  2181. inc XH ; Add 1
  2182. mov Temp2, XH
  2183. mov XH, Temp1
  2184. andi XH, 0xFC ; Calculate L byte
  2185. rjmp calc_governor_store_target
  2186. calc_governor_target_low:
  2187. lds XH, Governor_Req_Pwm ; Load governor requested pwm
  2188. com XH ; Calculate 255-pwm (invert pwm)
  2189. ; Calculate comm period target (2 + 8*((255-Requested_Pwm)/256) - 0.25)
  2190. rol XH ; Msb to carry
  2191. rol XH ; To bit0
  2192. rol XH ; To bit1
  2193. rol XH ; To bit2
  2194. mov Temp2, XH ; Now 3 lsbs are valid for H
  2195. ror XH
  2196. mov Temp1, XH ; Now 5 msbs are valid for L
  2197. mov XH, Temp2
  2198. andi XH, 0x07 ; Calculate H byte
  2199. inc XH ; Add 1
  2200. inc XH ; Add 1 more
  2201. mov Temp2, XH
  2202. mov XH, Temp1
  2203. andi XH, 0xF8 ; Calculate L byte
  2204. calc_governor_subtract_025:
  2205. subi XH, 0x40 ; Subtract 0.25
  2206. mov Temp1, XH
  2207. sbc Temp2, Zero
  2208. calc_governor_store_target:
  2209. ; Store governor target
  2210. sts Gov_Target_L, Temp1
  2211. sts Gov_Target_H, Temp2
  2212. calc_governor_target_exit:
  2213. ret
  2214. .ENDIF
  2215. .IF MODE == 1 ; Tail
  2216. calc_governor_target:
  2217. ret
  2218. .ENDIF
  2219. .IF MODE == 2 ; Multi
  2220. calc_governor_target:
  2221. lds Temp1, Pgm_Gov_Mode ; Closed loop mode?
  2222. cpi Temp1, 4
  2223. breq calc_governor_target_exit ; No
  2224. governor_target_calc:
  2225. ; Stop governor for stop RC pulse
  2226. lds XH, New_Rcp ; Check RC pulse against stop value
  2227. subi XH, RCP_STOP ; Is pulse below stop value?
  2228. brcs governor_deactivate ; Yes - deactivate
  2229. rjmp governor_activate ; No - activate
  2230. governor_deactivate:
  2231. lds XH, Requested_Pwm ; Set current pwm to requested
  2232. sts Current_Pwm, XH
  2233. sts Gov_Target_L, Zero ; Set target to zero
  2234. sts Gov_Target_H, Zero
  2235. sts Gov_Integral_L, Zero ; Set integral to zero
  2236. sts Gov_Integral_H, Zero
  2237. sts Gov_Integral_X, Zero
  2238. cbr Flags0, (1<<GOV_ACTIVE)
  2239. rjmp calc_governor_target_exit
  2240. governor_activate:
  2241. lds Temp5, Pgm_Gov_Mode ; Store gov mode in Temp5
  2242. sbr Flags0, (1<<GOV_ACTIVE)
  2243. lds XH, Requested_Pwm ; Load requested pwm
  2244. sts Governor_Req_Pwm, XH ; Set governor requested pwm
  2245. ; Calculate comm period target 2*(51000/Requested_Pwm)
  2246. ldi Temp1, 0x38 ; Load 51000
  2247. ldi Temp2, 0xC7
  2248. lds Temp3, Comm_Period4x_L ; Load comm period
  2249. lds Temp4, Comm_Period4x_H
  2250. ; Set speed range. Bare Comm_Period4x corresponds to 400k rpm, because it is 500n units
  2251. lsr Temp4
  2252. ror Temp3 ; 200k eRPM range here
  2253. ; Check range
  2254. mov XH, Temp5
  2255. dec XH
  2256. breq governor_activate_range_set ; 200k eRPM? - branch
  2257. governor_activate_100k:
  2258. lsr Temp4
  2259. ror Temp3 ; 100k eRPM range here
  2260. mov XH, Temp5 ; Check range again
  2261. dec XH
  2262. dec XH
  2263. breq governor_activate_range_set ; 100k eRPM? - branch
  2264. governor_activate_50k:
  2265. lsr Temp4
  2266. ror Temp3 ; 50k eRPM range here
  2267. governor_activate_range_set:
  2268. rcall div_u16_by_u16
  2269. ; Store governor target
  2270. sts Gov_Target_L, Temp1
  2271. sts Gov_Target_H, Temp2
  2272. calc_governor_target_exit:
  2273. ret
  2274. .ENDIF
  2275. ; Second governor routine - calculate governor proportional error
  2276. calc_governor_prop_error:
  2277. ; Exit if governor is inactive
  2278. sbrs Flags0, GOV_ACTIVE
  2279. rjmp calc_governor_prop_error_exit
  2280. .IF MODE <= 1 ; Main or tail
  2281. ; Load comm period and divide by 2
  2282. lds Temp2, Comm_Period4x_H
  2283. lsr Temp2
  2284. lds Temp1, Comm_Period4x_L
  2285. ror Temp1
  2286. ; Calculate error
  2287. lds XH, Gov_Target_L
  2288. sub XH, Temp1
  2289. mov Temp1, XH
  2290. lds XH, Gov_Target_H
  2291. sbc XH, Temp2
  2292. mov Temp2, XH
  2293. .ENDIF
  2294. .IF MODE == 2 ; Multi
  2295. ; Calculate error
  2296. lds Temp1, Gov_Target_L
  2297. lds XH, Governor_Req_Pwm
  2298. sub Temp1, XH
  2299. lds Temp2, Gov_Target_H
  2300. sbc Temp2, Zero
  2301. .ENDIF
  2302. ; Check error and limit
  2303. brcc governor_check_prop_limit_pos ; Check carry
  2304. cpi Temp1, 0x80 ; Is error too negative?
  2305. ldi XH, 0xFF
  2306. cpc Temp2, XH
  2307. brcs governor_limit_prop_error_neg ; Yes - limit
  2308. rjmp governor_store_prop_error
  2309. governor_check_prop_limit_pos:
  2310. cpi Temp1, 0x7F ; Is error too positive?
  2311. cpc Temp2, Zero
  2312. brcc governor_limit_prop_error_pos ; Yes - limit
  2313. rjmp governor_store_prop_error
  2314. governor_limit_prop_error_pos:
  2315. ldi Temp1, 0x7F ; Limit to max positive (2's complement)
  2316. ldi Temp2, 0x00
  2317. rjmp governor_store_prop_error
  2318. governor_limit_prop_error_neg:
  2319. ldi Temp1, 0x80 ; Limit to max negative (2's complement)
  2320. ldi Temp2, 0xFF
  2321. governor_store_prop_error:
  2322. ; Store proportional
  2323. sts Gov_Proportional_L, Temp1
  2324. sts Gov_Proportional_H, Temp2
  2325. calc_governor_prop_error_exit:
  2326. ret
  2327. ; Third governor routine - calculate governor integral error
  2328. calc_governor_int_error:
  2329. ; Exit if governor is inactive
  2330. sbrs Flags0, GOV_ACTIVE
  2331. rjmp calc_governor_int_error_exit
  2332. ; Add proportional to integral
  2333. lds Temp1, Gov_Proportional_L
  2334. lds XH, Gov_Integral_L
  2335. add Temp1, XH
  2336. lds Temp2, Gov_Proportional_H
  2337. lds XH, Gov_Integral_H
  2338. adc Temp2, XH
  2339. ldi Temp3, 0 ; Sign extend high byte
  2340. lds Temp4, Gov_Proportional_H
  2341. tst Temp4
  2342. brpl PC+2
  2343. dec Temp3
  2344. lds XH, Gov_Integral_X
  2345. adc Temp3, XH
  2346. ; Check integral and limit
  2347. brpl governor_check_int_limit_pos ; Check sign bit
  2348. cpi Temp3, 0xF0 ; Is error too negative?
  2349. brcs governor_limit_int_error_neg ; Yes - limit
  2350. rjmp governor_check_pwm
  2351. governor_check_int_limit_pos:
  2352. cpi Temp3, 0x0F ; Is error too positive?
  2353. brcc governor_limit_int_error_pos ; Yes - limit
  2354. rjmp governor_check_pwm
  2355. governor_limit_int_error_pos:
  2356. ldi Temp1, 0xFF ; Limit to max positive (2's complement)
  2357. ldi Temp2, 0xFF
  2358. ldi Temp3, 0x0F
  2359. rjmp governor_check_pwm
  2360. governor_limit_int_error_neg:
  2361. ldi Temp1, 0x00 ; Limit to max negative (2's complement)
  2362. ldi Temp2, 0x00
  2363. ldi Temp3, 0xF0
  2364. governor_check_pwm:
  2365. ; Check current pwm
  2366. lds Temp4, Current_Pwm ; Is current pwm at or above pwm limit?
  2367. lds XH, Pwm_Limit
  2368. cp Temp4, XH
  2369. brcc governor_int_max_pwm ; Yes - branch
  2370. tst Temp4 ; Is current pwm at zero?
  2371. breq governor_int_min_pwm ; Yes - branch
  2372. rjmp governor_store_int_error ; No - store integral error
  2373. governor_int_max_pwm:
  2374. lds XH, Gov_Proportional_H
  2375. tst XH
  2376. brmi calc_governor_int_error_exit ; Is proportional error negative - branch (high byte is always zero)
  2377. rjmp governor_store_int_error ; Positive - store integral error
  2378. governor_int_min_pwm:
  2379. lds XH, Gov_Proportional_H
  2380. tst XH
  2381. brpl calc_governor_int_error_exit ; Is proportional error positive - branch (high byte is always zero)
  2382. governor_store_int_error:
  2383. ; Store integral
  2384. sts Gov_Integral_L, Temp1
  2385. sts Gov_Integral_H, Temp2
  2386. sts Gov_Integral_X, Temp3
  2387. calc_governor_int_error_exit:
  2388. ret
  2389. ; Fourth governor routine - calculate governor proportional correction
  2390. calc_governor_prop_correction:
  2391. ; Exit if governor is inactive
  2392. sbrs Flags0, GOV_ACTIVE
  2393. rjmp calc_governor_prop_corr_exit
  2394. ; Load proportional gain
  2395. lds Temp3, Pgm_Gov_P_Gain_Decoded; Load proportional gain and store in Temp3
  2396. ; Load proportional
  2397. lds Temp1, Gov_Proportional_L ; Nominal multiply by 2
  2398. lsl Temp1
  2399. lds Temp2, Gov_Proportional_H
  2400. rol Temp2
  2401. ; Apply gain
  2402. rcall mult_s16_by_u8_div_16
  2403. ; Check error and limit (to low byte)
  2404. tst Temp2
  2405. brpl governor_check_prop_corr_limit_pos ; Check sign bit
  2406. cpi Temp1, 0x80 ; Is error too negative?
  2407. ldi XH, 0xFF
  2408. cpc Temp2, XH
  2409. brcs governor_limit_prop_corr_neg ; Yes - limit
  2410. rjmp governor_apply_prop_corr
  2411. governor_check_prop_corr_limit_pos:
  2412. cpi Temp1, 0x7F ; Is error too positive?
  2413. cpc Temp2, Zero
  2414. brcc governor_limit_prop_corr_pos ; Yes - limit
  2415. rjmp governor_apply_prop_corr
  2416. governor_limit_prop_corr_pos:
  2417. ldi Temp1, 0x7F ; Limit to max positive (2's complement)
  2418. ldi Temp2, 0x00
  2419. rjmp governor_apply_prop_corr
  2420. governor_limit_prop_corr_neg:
  2421. ldi Temp1, 0x80 ; Limit to max negative (2's complement)
  2422. ldi Temp2, 0xFF
  2423. governor_apply_prop_corr:
  2424. ; Test proportional sign
  2425. tst Temp1
  2426. brmi governor_corr_neg_prop ; If proportional negative - go to correct negative
  2427. ; Subtract positive proportional
  2428. lds XH, Governor_Req_Pwm
  2429. sub XH, Temp1
  2430. mov Temp1, XH
  2431. ; Check result
  2432. brcs governor_corr_prop_min_pwm ; Is result negative?
  2433. cpi Temp1, 1 ; Is result below pwm min?
  2434. brcs governor_corr_prop_min_pwm ; Yes
  2435. rjmp governor_store_prop_corr ; No - store proportional correction
  2436. governor_corr_prop_min_pwm:
  2437. ldi Temp1, 1 ; Load minimum pwm
  2438. rjmp governor_store_prop_corr
  2439. governor_corr_neg_prop:
  2440. ; Add negative proportional
  2441. com Temp1
  2442. subi Temp1, 0xFF ; "Add one"
  2443. lds XH, Governor_Req_Pwm
  2444. add Temp1, XH
  2445. ; Check result
  2446. brcs governor_corr_prop_max_pwm ; Is result above max?
  2447. rjmp governor_store_prop_corr ; No - store proportional correction
  2448. governor_corr_prop_max_pwm:
  2449. ldi Temp1, 255 ; Load maximum pwm
  2450. governor_store_prop_corr:
  2451. ; Store proportional pwm
  2452. sts Gov_Prop_Pwm, Temp1
  2453. calc_governor_prop_corr_exit:
  2454. ret
  2455. ; Fifth governor routine - calculate governor integral correction
  2456. calc_governor_int_correction:
  2457. ; Exit if governor is inactive
  2458. sbrs Flags0, GOV_ACTIVE
  2459. rjmp calc_governor_int_corr_exit
  2460. ; Load integral gain
  2461. lds Temp3, Pgm_Gov_I_Gain_Decoded ; Load integral gain and store in Temp3
  2462. ; Load integral
  2463. lds Temp1, Gov_Integral_H
  2464. lds Temp2, Gov_Integral_X
  2465. ; Apply gain
  2466. rcall mult_s16_by_u8_div_16
  2467. ; Check integral and limit
  2468. tst Temp2
  2469. brpl governor_check_int_corr_limit_pos ; Check sign bit
  2470. cpi Temp1, 0x01 ; Is integral too negative?
  2471. ldi XH, 0xFF
  2472. cpc Temp2, XH
  2473. brcs governor_limit_int_corr_neg ; Yes - limit
  2474. rjmp governor_apply_int_corr
  2475. governor_check_int_corr_limit_pos:
  2476. cpi Temp1, 0xFF ; Is integral too positive?
  2477. cpc Temp2, Zero
  2478. brcc governor_limit_int_corr_pos ; Yes - limit
  2479. rjmp governor_apply_int_corr
  2480. governor_limit_int_corr_pos:
  2481. ldi Temp1, 0xFF ; Limit to max positive (2's complement)
  2482. ldi Temp2, 0x00
  2483. rjmp governor_apply_int_corr
  2484. governor_limit_int_corr_neg:
  2485. ldi Temp1, 0x01 ; Limit to max negative (2's complement)
  2486. ldi Temp2, 0xFF
  2487. governor_apply_int_corr:
  2488. ; Test integral sign
  2489. tst Temp2
  2490. brmi governor_corr_neg_int ; If integral negative - go to correct negative
  2491. ; Subtract positive integral
  2492. lds XH, Gov_Prop_Pwm
  2493. sub XH, Temp1
  2494. mov Temp1, XH
  2495. ; Check result
  2496. brcs governor_corr_int_min_pwm ; Is result negative?
  2497. cpi Temp1, 1 ; Is result below pwm min?
  2498. brcs governor_corr_int_min_pwm ; Yes
  2499. rjmp governor_store_int_corr ; No - store correction
  2500. governor_corr_int_min_pwm:
  2501. ldi Temp1, 0 ; Load minimum pwm
  2502. rjmp governor_store_int_corr
  2503. governor_corr_neg_int:
  2504. ; Add negative integral
  2505. com Temp1
  2506. subi Temp1, 0xFF ; "Add one"
  2507. lds XH, Gov_Prop_Pwm
  2508. add Temp1, XH
  2509. ; Check result
  2510. brcs governor_corr_int_max_pwm ; Is result above max?
  2511. rjmp governor_store_int_corr ; No - store correction
  2512. governor_corr_int_max_pwm:
  2513. ldi Temp1, 255 ; Load maximum pwm
  2514. governor_store_int_corr:
  2515. ; Store current pwm
  2516. sts Current_Pwm, Temp1
  2517. calc_governor_int_corr_exit:
  2518. ret
  2519. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  2520. ;
  2521. ; Measure lipo cells
  2522. ;
  2523. ; No assumptions
  2524. ;
  2525. ; Measure voltage and calculate lipo cells
  2526. ;
  2527. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  2528. measure_lipo_cells:
  2529. .IF MODE == 1 ; Tail
  2530. ; If tail, then exit
  2531. rjmp measure_lipo_exit
  2532. .ENDIF
  2533. measure_lipo_start:
  2534. ; Set commutation to BpFET on
  2535. rcall comm5comm6
  2536. ; Start adc
  2537. Start_Adc XH
  2538. ; Wait for ADC reference to settle, and then start again
  2539. rcall wait1ms
  2540. Start_Adc XH
  2541. ; Wait for ADC conversion to complete
  2542. measure_lipo_wait_adc:
  2543. Get_Adc_Status XH
  2544. sbrc XH, ADSC
  2545. rjmp measure_lipo_wait_adc
  2546. ; Read ADC result
  2547. Read_Adc_Result Temp1, Temp2
  2548. ; Stop ADC
  2549. Stop_Adc XH
  2550. ; Switch power off
  2551. rcall switch_power_off
  2552. ; Set limit step
  2553. ldi Temp3, ADC_LIMIT_L
  2554. sts Lipo_Adc_Limit_L, Temp3
  2555. ldi Temp4, ADC_LIMIT_H
  2556. sts Lipo_Adc_Limit_H, Temp4
  2557. mov Temp6, Temp4 ; Divide 3.0V value by 2
  2558. lsr Temp6
  2559. mov Temp5, Temp3
  2560. lsr Temp5
  2561. add Temp5, Temp3 ; Calculate 1.5*3.0V=4.5V value
  2562. adc Temp6, Temp4
  2563. mov Temp3, Temp5 ; Copy step
  2564. mov Temp4, Temp6
  2565. measure_lipo_cell_loop:
  2566. ; Check voltage against xS lower limit
  2567. cp Temp1, Temp3 ; Voltage above limit?
  2568. cpc Temp2, Temp4
  2569. brcs measure_lipo_adjust ; No - branch
  2570. ; Set xS voltage limit
  2571. lds Temp7, Lipo_Adc_Limit_L
  2572. ldi XH, ADC_LIMIT_L
  2573. add XH, Temp7
  2574. sts Lipo_Adc_Limit_L, XH
  2575. lds Temp7, Lipo_Adc_Limit_H
  2576. ldi XH, ADC_LIMIT_H
  2577. adc XH, Temp7
  2578. sts Lipo_Adc_Limit_H, XH
  2579. ; Set (x+1)S lower limit
  2580. add Temp3, Temp5 ; Add step
  2581. adc Temp4, Temp6
  2582. rjmp measure_lipo_cell_loop ; Check for one more battery cell
  2583. measure_lipo_adjust:
  2584. lds Temp7, Lipo_Adc_Limit_L
  2585. lds Temp8, Lipo_Adc_Limit_H
  2586. ; Calculate 3.125%
  2587. lds Temp2, Lipo_Adc_Limit_H
  2588. lsr Temp2
  2589. lds Temp1, Lipo_Adc_Limit_L
  2590. ror Temp1 ; After this 50%
  2591. lsr Temp2
  2592. ror Temp1 ; After this 25%
  2593. lds XH, Lipo_Adc_Limit_L ; Set adc reference for voltage compensation
  2594. add XH, Temp1
  2595. sts Lipo_Adc_Reference_L, XH
  2596. lds XH, Lipo_Adc_Limit_H
  2597. adc XH, Temp2
  2598. sts Lipo_Adc_Reference_H, XH
  2599. ; Divide three times to get to 3.125%
  2600. ldi Temp3, 3
  2601. measure_lipo_divide_loop:
  2602. lsr Temp2
  2603. ror Temp1
  2604. dec Temp3
  2605. brne measure_lipo_divide_loop
  2606. ; Add the programmed number of 0.1V (or 3.125% increments)
  2607. lds Temp3, Pgm_Low_Voltage_Lim ; Load programmed limit
  2608. dec Temp3
  2609. brne measure_lipo_limit_on ; Is low voltage limiting on?
  2610. sts Lipo_Adc_Limit_L, Zero ; No - set limit to zero
  2611. sts Lipo_Adc_Limit_H, Zero
  2612. rjmp measure_lipo_exit
  2613. measure_lipo_limit_on:
  2614. dec Temp3
  2615. breq measure_lipo_update
  2616. measure_lipo_add_loop:
  2617. add Temp7, Temp1 ; Add 3.125%
  2618. adc Temp8, Temp2
  2619. dec Temp3
  2620. brne measure_lipo_add_loop
  2621. measure_lipo_update:
  2622. ; Set ADC limit
  2623. sts Lipo_Adc_Limit_L, Temp7
  2624. sts Lipo_Adc_Limit_H, Temp8
  2625. measure_lipo_exit:
  2626. ret
  2627. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  2628. ;
  2629. ; Check temperature, power supply voltage and limit power
  2630. ;
  2631. ; No assumptions
  2632. ;
  2633. ; Used to limit main motor power in order to maintain the required voltage
  2634. ;
  2635. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  2636. check_temp_voltage_and_limit_power:
  2637. ; Load programmed low voltage limit
  2638. lds Temp3, Pgm_Low_Voltage_Lim ; Store in Temp3
  2639. ; Wait for ADC conversion to complete
  2640. Get_Adc_Status XH
  2641. sbrc XH, ADSC
  2642. rjmp check_temp_voltage_and_limit_power
  2643. ; Read ADC result
  2644. Read_Adc_Result Temp1, Temp2
  2645. ; Stop ADC
  2646. Stop_Adc XH
  2647. lds XH, Adc_Conversion_Cnt ; Increment conversion counter
  2648. inc XH
  2649. sts Adc_Conversion_Cnt, XH
  2650. cpi XH, TEMP_CHECK_RATE ; Is conversion count equal to temp rate?
  2651. brcs check_voltage_start ; No - check voltage
  2652. sts Adc_Conversion_Cnt, Zero ; Yes - temperature check. Reset counter
  2653. tst Temp2 ; Is temperature ADC reading below 256?
  2654. breq temp_average_inc_dec ; Yes - proceed
  2655. lds XH, Current_Average_Temp_Adc ; No - increment average
  2656. cpi XH, 0xFF
  2657. breq temp_average_updated ; Already max - no change
  2658. rjmp temp_average_inc ; Increment
  2659. temp_average_inc_dec:
  2660. lds XH, Current_Average_Temp_Adc ; Check if current temp ADC is above or below average
  2661. cp Temp1, XH
  2662. breq temp_average_updated ; Equal - no change
  2663. brcc temp_average_inc ; Above - increment average
  2664. tst XH ; Below - decrement average if average is not already zero
  2665. breq temp_average_updated
  2666. temp_average_dec:
  2667. dec XH ; Decrement average
  2668. rjmp temp_average_updated
  2669. temp_average_inc:
  2670. inc XH ; Increment average
  2671. breq temp_average_dec
  2672. temp_average_updated:
  2673. lds Temp1, Pwm_Limit
  2674. sts Current_Average_Temp_Adc, XH
  2675. cpi XH, TEMP_LIMIT ; Is temp ADC above first limit?
  2676. brcc temp_check_exit ; Yes - exit
  2677. ldi Temp1, 192 ; No - limit pwm
  2678. cpi XH, (TEMP_LIMIT-TEMP_LIMIT_STEP) ; Is temp ADC above second limit
  2679. brcc temp_check_exit ; Yes - exit
  2680. ldi Temp1, 128 ; No - limit pwm
  2681. cpi XH, (TEMP_LIMIT-2*TEMP_LIMIT_STEP) ; Is temp ADC above third limit
  2682. brcc temp_check_exit ; Yes - exit
  2683. ldi Temp1, 64 ; No - limit pwm
  2684. cpi XH, (TEMP_LIMIT-3*TEMP_LIMIT_STEP) ; Is temp ADC above final limit
  2685. brcc temp_check_exit ; Yes - exit
  2686. ldi Temp1, 0 ; No - limit pwm
  2687. temp_check_exit:
  2688. sts Pwm_Limit, Temp1 ; Set pwm limit
  2689. Set_Adc_Ip_Volt ; Select adc input for next conversion
  2690. ret
  2691. check_voltage_start:
  2692. .IF (MODE == 0) || (MODE == 2) ; Main or multi
  2693. ; Check if low voltage limiting is enabled
  2694. cpi Temp3, 1 ; Is low voltage limit disabled?
  2695. breq check_voltage_good ; Yes - voltage declared good
  2696. ; Check if ADC is saturated
  2697. cpi Temp1, 0xFF
  2698. ldi XH, 3
  2699. cpc Temp2, XH
  2700. brcc check_voltage_good ; ADC saturated, can not make judgement
  2701. ; Check voltage against limit
  2702. lds XH, Lipo_Adc_Limit_L
  2703. cp Temp1, XH
  2704. lds XH, Lipo_Adc_Limit_H
  2705. cpc Temp2, XH
  2706. brcc check_voltage_good ; If voltage above limit - branch
  2707. ; Decrease pwm limit
  2708. lds XH, Pwm_Limit
  2709. tst XH
  2710. breq check_voltage_lim ; If limit zero - branch
  2711. dec XH ; Decrement limit
  2712. sts Pwm_Limit, XH
  2713. rjmp check_voltage_lim
  2714. check_voltage_good:
  2715. ; Increase pwm limit
  2716. lds XH, Pwm_Limit
  2717. cpi XH, 0xFF
  2718. breq check_voltage_lim ; If limit max - branch
  2719. inc XH ; Increment limit
  2720. sts Pwm_Limit, XH
  2721. check_voltage_lim:
  2722. lds Temp1, Pwm_Limit ; Set limit
  2723. lds XH, Current_Pwm
  2724. sub XH, Temp1
  2725. brcc check_voltage_spoolup_lim ; If current pwm above limit - branch and limit
  2726. lds Temp1, Current_Pwm ; Set current pwm (no limiting)
  2727. check_voltage_spoolup_lim:
  2728. ; Slow spoolup
  2729. lds XH, Pwm_Limit_Spoolup
  2730. cp Temp1, XH
  2731. brcs check_voltage_exit ; If current pwm below limit - branch
  2732. lds Temp1, Pwm_Limit_Spoolup
  2733. lds XH, Pwm_Limit_Spoolup ; Check if spoolup limit is max
  2734. cpi XH, 0xFF
  2735. breq check_voltage_exit ; If max - branch
  2736. lds XH, Pwm_Limit_Spoolup ; Set pwm limit to spoolup limit during ramp (to avoid governor integral buildup)
  2737. sts Pwm_Limit, XH
  2738. check_voltage_exit:
  2739. mov Current_Pwm_Limited, Temp1
  2740. .ENDIF
  2741. ; Set adc mux for next conversion
  2742. lds XH, Adc_Conversion_Cnt ; Is next conversion for temperature?
  2743. cpi XH, (TEMP_CHECK_RATE-1)
  2744. brne check_voltage_ret
  2745. Set_Adc_Ip_Temp ; Select temp sensor for next conversion
  2746. check_voltage_ret:
  2747. ret
  2748. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  2749. ;
  2750. ; Set startup PWM routine
  2751. ;
  2752. ; No assumptions
  2753. ;
  2754. ; Used for pwm control during startup
  2755. ;
  2756. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  2757. set_startup_pwm:
  2758. ; Adjust startup power
  2759. ldi Temp1, PWM_START ; Set power
  2760. cli ; Disable interrupts in order to avoid interference with mul ops in interrupt routines
  2761. lds XH, Pgm_Startup_Pwr_Decoded ; Multiply startup power by programmed value
  2762. mul Temp1, XH
  2763. mov Temp1, Mul_Res_H ; Transfer result
  2764. lsl Mul_Res_L ; Multiply result by 2 (unity gain is 128)
  2765. rol Temp1
  2766. sei
  2767. lds XH, Pwm_Limit ; Check against limit
  2768. cp Temp1, XH
  2769. brcs startup_pwm_set_pwm ; If pwm below limit - branch
  2770. lds Temp1, Pwm_Limit ; Limit pwm
  2771. startup_pwm_set_pwm:
  2772. ; Set pwm variables
  2773. sts Requested_Pwm, Temp1 ; Update requested pwm
  2774. sts Current_Pwm, Temp1 ; Update current pwm
  2775. mov Current_Pwm_Limited, Temp1 ; Update limited version of current pwm
  2776. sts Pwm_Spoolup_Beg, Temp1 ; Update spoolup beginning pwm
  2777. startup_pwm_exit:
  2778. ret
  2779. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  2780. ;
  2781. ; Initialize all timings routine
  2782. ;
  2783. ; No assumptions
  2784. ;
  2785. ; Part of initialization before motor start
  2786. ;
  2787. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  2788. initialize_all_timings:
  2789. sts Comm_Period4x_L, Zero ; Set commutation period registers
  2790. ldi XH, 0x08
  2791. sts Comm_Period4x_H, XH
  2792. ret
  2793. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  2794. ;
  2795. ; Calculate next commutation timing routine
  2796. ;
  2797. ; No assumptions
  2798. ;
  2799. ; Called immediately after each commutation
  2800. ; Also sets up timer 1 to wait advance timing
  2801. ;
  2802. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  2803. calc_next_comm_timing: ; Entry point for run phase
  2804. lds Temp3, Wt_Advance_L ; Set up advance timing wait
  2805. lds Temp4, Wt_Advance_H
  2806. cli ; Disable interrupts while reading timer 1
  2807. Read_TCNT1L Temp1
  2808. Read_TCNT1H Temp2
  2809. add Temp3, Temp1 ; Set new output compare value
  2810. adc Temp4, Temp2
  2811. Set_OCR1AH Temp4 ; Update high byte first to avoid false output compare
  2812. Set_OCR1AL Temp3
  2813. sei ; Enable interrupts
  2814. sbr Flags0, (1<<OC1A_PENDING) ; Set timer output compare pending flag
  2815. ; Calculate this commutation time
  2816. lds Temp3, Prev_Comm_L
  2817. lds Temp4, Prev_Comm_H
  2818. sts Prev_Comm_L, Temp1 ; Store timestamp as previous commutation
  2819. sts Prev_Comm_H, Temp2
  2820. sub Temp1, Temp3 ; Calculate the new commutation time
  2821. sbc Temp2, Temp4
  2822. ; Calculate next zero cross scan timeout
  2823. lds Temp3, Comm_Period4x_L ; Comm_Period4x(-l-h-x) holds the time of 4 commutations
  2824. lds Temp4, Comm_Period4x_H
  2825. mov Temp6, Temp4
  2826. mov Temp5, Temp3
  2827. lsr Temp6 ; Divide by 2
  2828. ror Temp5
  2829. lsr Temp6 ; Divide by 2 again
  2830. ror Temp5
  2831. sub Temp3, Temp5 ; Subtract a quarter
  2832. sbc Temp4, Temp6
  2833. add Temp3, Temp1 ; Add the new time
  2834. adc Temp4, Temp2
  2835. sts Comm_Period4x_L, Temp3 ; Store Comm_Period4x_X
  2836. sts Comm_Period4x_H, Temp4
  2837. brcs calc_next_comm_slow ; If period larger than 0xffff - go to slow case
  2838. ret
  2839. calc_next_comm_slow:
  2840. ldi XH, 0xFF
  2841. sts Comm_Period4x_L, XH ; Set commutation period registers to very slow timing (0xffff)
  2842. sts Comm_Period4x_H, XH
  2843. ret
  2844. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  2845. ;
  2846. ; Setup zero cross scan wait
  2847. ;
  2848. ; No assumptions
  2849. ;
  2850. ; Sets up timer 1 to wait the zero cross scan wait time
  2851. ;
  2852. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  2853. setup_zc_scan_wait:
  2854. lds Temp3, Wt_Zc_Scan_L ; Set wait to zero cross scan value
  2855. lds Temp4, Wt_Zc_Scan_H
  2856. cli ; Disable interrupts while reading timer 1
  2857. Read_TCNT1L Temp1
  2858. Read_TCNT1H Temp2
  2859. add Temp1, Temp3 ; Set new output compare value
  2860. adc Temp2, Temp4
  2861. Set_OCR1AH Temp2 ; Update high byte first to avoid false output compare
  2862. Set_OCR1AL Temp1
  2863. sei ; Enable interrupts
  2864. sbr Flags0, (1<<OC1A_PENDING)
  2865. ret
  2866. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  2867. ;
  2868. ; Wait advance timing routine
  2869. ;
  2870. ; No assumptions
  2871. ;
  2872. ; Waits for the advance timing to elapse, waits one zero cross
  2873. ; wait and sets up the next zero cross wait
  2874. ;
  2875. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  2876. wait_advance_timing:
  2877. ldi XH, 1 ; Default one zero cross scan wait (prevents squealing that can happen if two are used when demag comp is off)
  2878. mov Temp8, XH
  2879. lds XH, Pgm_Demag_Comp ; Load programmed demag compensation
  2880. dec XH
  2881. breq wait_advance_timing_wait
  2882. ldi XH, 2 ; Do two zero cross scan waits when demag comp is on (gives more correct blind advance)
  2883. mov Temp8, XH
  2884. wait_advance_timing_wait:
  2885. sbrc Flags0, OC1A_PENDING
  2886. rjmp wait_advance_timing_wait
  2887. rcall setup_zc_scan_wait ; Setup wait time
  2888. dec Temp8
  2889. brne wait_advance_timing_wait
  2890. ret
  2891. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  2892. ;
  2893. ; Calculate new wait times routine
  2894. ;
  2895. ; No assumptions
  2896. ;
  2897. ; Calculates new wait times
  2898. ;
  2899. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  2900. calc_new_wait_times:
  2901. ; Load programmed commutation timing
  2902. lds Temp8, Pgm_Comm_Timing ; Store in Temp8
  2903. ldi XH, (COMM_TIME_RED<<1)
  2904. mov Temp7, XH
  2905. .IF MODE == 2
  2906. lds Temp1, Comm_Period4x_H ; Higher reduction for higher speed in MULTI mode
  2907. cpi Temp1, 4 ; A COMM_TIME_RED of 6 gives good acceleration performance on pancake motor at high voltage
  2908. brcs calc_new_wait_red_set ; A COMM_TIME_RED of 10 gives good high speed performance for a small motor
  2909. ldi Temp1, 4
  2910. calc_new_wait_red_set:
  2911. lsl Temp1
  2912. sub Temp7, Temp1
  2913. .ENDIF
  2914. sbrs Flags1, STARTUP_PHASE ; Set timing for start
  2915. rjmp calc_new_wait_dir_start_set
  2916. ldi XH, 3 ; Set medium timing
  2917. mov Temp8, XH
  2918. mov Temp7, Zero ; Set no comm time reduction
  2919. calc_new_wait_dir_start_set:
  2920. ; Load current commutation timing
  2921. lds Temp2, Comm_Period4x_H ; Load Comm_Period4x
  2922. lds Temp1, Comm_Period4x_L
  2923. ldi Temp3, 4 ; Divide 4 times
  2924. divide_wait_times:
  2925. lsr Temp2 ; Divide by 2
  2926. ror Temp1
  2927. dec Temp3
  2928. brne divide_wait_times
  2929. sub Temp1, Temp7
  2930. sbc Temp2, Zero
  2931. brcs load_min_time ; Check that result is still positive
  2932. mov XH, Temp1
  2933. subi XH, (COMM_TIME_MIN<<1)
  2934. mov XH, Temp2
  2935. sbc XH, Zero
  2936. brcc adjust_timing ; Check that result is still above minumum
  2937. load_min_time:
  2938. ldi Temp1, (COMM_TIME_MIN<<1)
  2939. ldi Temp2, 0
  2940. adjust_timing:
  2941. mov Temp4, Temp2 ; Copy values
  2942. mov Temp3, Temp1
  2943. mov Temp6, Temp2
  2944. mov Temp5, Temp1
  2945. lsr Temp6 ; Divide by 2
  2946. ror Temp5
  2947. mov XH, Temp8 ; (Temp8 has Pgm_Comm_Timing)
  2948. cpi XH, 3 ; Is timing normal?
  2949. breq store_times_decrease ; Yes - branch
  2950. sbrc XH, 0 ; If an odd number - branch
  2951. rjmp adjust_timing_two_steps
  2952. add Temp1, Temp5 ; Add 7.5� and store in Temp1/2
  2953. adc Temp2, Temp6
  2954. mov Temp3, Temp5 ; Store 7.5� in Temp3/4
  2955. mov Temp4, Temp6
  2956. rjmp store_times_up_or_down
  2957. adjust_timing_two_steps:
  2958. lsl Temp1 ; Add 15� and store in Temp1/2
  2959. rol Temp2
  2960. ldi Temp3, (COMM_TIME_MIN<<1); Store minimum time in Temp3/4
  2961. ldi Temp4, 0
  2962. store_times_up_or_down:
  2963. mov XH, Temp8 ; Is timing higher than normal?
  2964. cpi XH, 3
  2965. brcs store_times_decrease ; No - branch
  2966. store_times_increase:
  2967. sts Wt_Comm_L, Temp3 ; Now commutation time (~60�) divided by 4 (~15� nominal)
  2968. sts Wt_Comm_H, Temp4
  2969. sts Wt_Advance_L, Temp1 ; New commutation advance time (~15� nominal)
  2970. sts Wt_Advance_H, Temp2
  2971. sts Wt_Zc_Scan_L, Temp5 ; Use this value for zero cross scan delay (7.5�)
  2972. sts Wt_Zc_Scan_H, Temp6
  2973. ret
  2974. store_times_decrease:
  2975. sts Wt_Comm_L, Temp1 ; Now commutation time (~60�) divided by 4 (~15� nominal)
  2976. sts Wt_Comm_H, Temp2
  2977. sts Wt_Advance_L, Temp3 ; New commutation advance time (~15� nominal)
  2978. sts Wt_Advance_H, Temp4
  2979. sts Wt_Zc_Scan_L, Temp5 ; Use this value for zero cross scan delay (7.5�)
  2980. sts Wt_Zc_Scan_H, Temp6
  2981. ret
  2982. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  2983. ;
  2984. ; Wait before zero cross scan routine
  2985. ;
  2986. ; No assumptions
  2987. ;
  2988. ; Waits for the zero cross scan wait time to elapse
  2989. ; Also sets up timer 3 to wait the zero cross scan timeout time
  2990. ;
  2991. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  2992. wait_before_zc_scan:
  2993. sbrc Flags0, OC1A_PENDING
  2994. rjmp wait_before_zc_scan
  2995. lds Temp3, Comm_Period4x_L ; Set wait to zero comm period 4x value
  2996. lds Temp4, Comm_Period4x_H
  2997. cli ; Disable interrupts while reading timer 1
  2998. Read_TCNT1L Temp1
  2999. Read_TCNT1H Temp2
  3000. add Temp1, Temp3 ; Set new output compare value
  3001. adc Temp2, Temp4
  3002. Set_OCR1AH Temp2 ; Update high byte first to avoid false output compare
  3003. Set_OCR1AL Temp1
  3004. sei ; Enable interrupts
  3005. sbr Flags0, (1<<OC1A_PENDING)
  3006. ret
  3007. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  3008. ;
  3009. ; Wait for comparator to go low/high routines
  3010. ;
  3011. ; No assumptions
  3012. ;
  3013. ; Waits for the zero cross scan wait time to elapse
  3014. ; Then scans for comparator going low/high
  3015. ;
  3016. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  3017. wait_for_comp_out_low:
  3018. sts Comp_Wait_Reads, Zero
  3019. ldi Temp3, 0 ; Desired comparator output
  3020. rjmp wait_for_comp_out_start
  3021. wait_for_comp_out_high:
  3022. sts Comp_Wait_Reads, Zero
  3023. ldi Temp3, (1<<ACO) ; Desired comparator output
  3024. wait_for_comp_out_start:
  3025. sei ; Enable interrupts
  3026. lds XH, Comp_Wait_Reads
  3027. inc XH
  3028. sts Comp_Wait_Reads, XH
  3029. sbrs Flags0, OC1A_PENDING ; Has zero cross scan timeout elapsed?
  3030. ret ; Yes - return
  3031. ; Select number of comparator readings based upon current rotation speed
  3032. lds XH, Comm_Period4x_H ; Load rotation period
  3033. lsr XH ; Divide by 4
  3034. lsr XH
  3035. mov Temp1, XH
  3036. inc Temp1 ; Add one to be sure it is always larger than zero
  3037. breq comp_wait_on_comp_able ; If minimum number of readings - jump directly to reading
  3038. ; For damped mode, do fewer comparator readings (since comparator info is primarily only available in the pwm on period)
  3039. sbrs Flags2, PGM_PWMOFF_DAMPED
  3040. rjmp comp_wait_set_max_readings
  3041. lsr XH ; Divide by 4 again
  3042. lsr XH
  3043. mov Temp1, XH
  3044. inc Temp1 ; Add one to be sure it is always larger than zero
  3045. comp_wait_set_max_readings:
  3046. cpi Temp1, 10 ; Limit to a max of 10
  3047. brcs PC+2
  3048. ldi Temp1, 10
  3049. sbrs Flags2, PGM_PWM_HIGH_FREQ ; Jump if pwm frequency is low
  3050. rjmp comp_wait_on_comp_able
  3051. cpi Temp1, 4 ; Limit to a max of 4
  3052. brcs PC+2
  3053. ldi Temp1, 4
  3054. comp_wait_on_comp_able:
  3055. sbrc Flags0, OC1A_PENDING ; Has zero cross scan timeout elapsed?
  3056. rjmp comp_still_wait_on_comp_able
  3057. sei ; Enable interrupts
  3058. ret ; Yes - return
  3059. comp_still_wait_on_comp_able:
  3060. ldi Temp2, COMP_PWM_HIGH_ON_DELAY ; Wait time after pwm has been switched on (motor wire electrical settling)
  3061. sbrs Flags2, PGM_PWM_HIGH_FREQ
  3062. ldi Temp2, COMP_PWM_LOW_ON_DELAY
  3063. sei ; Enable interrupts
  3064. nop ; Allocate only just enough time to capture interrupt
  3065. nop
  3066. cli ; Disable interrupts
  3067. sbrc Flags0, PWM_ON ; If pwm on - proceed
  3068. rjmp pwm_wait_startup
  3069. ldi Temp2, COMP_PWM_HIGH_OFF_DELAY ; Wait time after pwm has been switched off (motor wire electrical settling)
  3070. sbrs Flags2, PGM_PWM_HIGH_FREQ
  3071. ldi Temp2, COMP_PWM_LOW_OFF_DELAY
  3072. sbrs Flags1, CURR_PWMOFF_COMP_ABLE ; If comparator is not usable in pwm off - go back
  3073. rjmp comp_wait_on_comp_able
  3074. pwm_wait_startup:
  3075. sbrs Flags1, STARTUP_PHASE ; Set a long delay from pwm on/off events during startup
  3076. rjmp pwm_wait
  3077. ldi Temp2, 120
  3078. pwm_wait:
  3079. .IF CLK_8M == 1
  3080. lsr Temp2
  3081. .ENDIF
  3082. Read_TCNT2 XH
  3083. lds Temp4, Pwm_Prev_Edge
  3084. sub XH, Temp4
  3085. sbc XH, Temp2
  3086. .IF (MODE == 1) && (DAMPED_MODE_ENABLE == 1) ; Assume same pwm cycle for fast tail escs
  3087. sbrc Flags1, STARTUP_PHASE
  3088. rjmp PC+2
  3089. brcs pwm_wait
  3090. brcs comp_wait_on_comp_able ; Re-evaluate pwm cycle during start
  3091. .ELSE
  3092. brcs comp_wait_on_comp_able ; Re-evaluate pwm cycle for slower escs
  3093. .ENDIF
  3094. comp_read:
  3095. Read_Comp_Out XH ; Read comparator output
  3096. andi XH, (1<<ACO)
  3097. cp XH, Temp3
  3098. brne PC+2 ; If comparator output is correct - proceed
  3099. rjmp wait_for_comp_out_start ; If comparator output is not correct - go back and restart
  3100. dec Temp1 ; Decrement readings counter - repeat comparator reading if not zero
  3101. brne comp_wait_on_comp_able
  3102. sei ; Enable interrupts
  3103. ret
  3104. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  3105. ;
  3106. ; Evaluate comparator integrity
  3107. ;
  3108. ; No assumptions
  3109. ;
  3110. ; Checks comparator signal behaviour versus expected behaviour
  3111. ;
  3112. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  3113. evaluate_comparator_integrity:
  3114. cbr Flags0, (1<<DEMAG_DETECTED) ; Clear demag detected flag
  3115. ; Check if demag compensation is enabled
  3116. lds XH, Pgm_Demag_Comp ; Load programmed demag compensation
  3117. dec XH
  3118. breq eval_comp_no_demag
  3119. ; Check if a demag situation has occurred
  3120. lds XH, Comp_Wait_Reads ; Check if there were no waits (there shall be some). If none a demag situation has occurred
  3121. dec XH
  3122. brne eval_comp_no_demag
  3123. sbrc Flags1, STARTUP_PHASE ; Do not set demag flag during start
  3124. rjmp eval_comp_no_demag
  3125. sbr Flags0, (1<<DEMAG_DETECTED) ; Set demag detected flag
  3126. eval_comp_no_demag:
  3127. sbrs Flags1, STARTUP_PHASE
  3128. rjmp eval_comp_check_timeout
  3129. lds XH, Startup_Ok_Cnt ; Increment ok counter
  3130. inc XH
  3131. sts Startup_Ok_Cnt, XH
  3132. sbrc Flags0, OC1A_PENDING
  3133. rjmp eval_comp_exit
  3134. sts Startup_Ok_Cnt, Zero ; Reset ok counter
  3135. rjmp eval_comp_exit
  3136. eval_comp_check_timeout:
  3137. sbrc Flags0, OC1A_PENDING ; Has timeout elapsed?
  3138. rjmp eval_comp_exit
  3139. pop XH ; Routine exit without "ret" command (dummy pops to increment stack pointer)
  3140. pop XH
  3141. rjmp run_to_wait_for_power_on ; Yes - exit run mode
  3142. eval_comp_exit:
  3143. ret
  3144. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  3145. ;
  3146. ; Setup commutation timing routine
  3147. ;
  3148. ; No assumptions
  3149. ;
  3150. ; Sets up and starts wait from commutation to zero cross
  3151. ;
  3152. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  3153. setup_comm_wait:
  3154. lds Temp3, Wt_Comm_L ; Set wait commutation value
  3155. lds Temp4, Wt_Comm_H
  3156. cli ; Disable interrupts while reading timer 1
  3157. Read_TCNT1L Temp1
  3158. Read_TCNT1H Temp2
  3159. add Temp1, Temp3 ; Set new output compare value
  3160. adc Temp2, Temp4
  3161. Set_OCR1AH Temp2 ; Update high byte first to avoid false output compare
  3162. Set_OCR1AL Temp1
  3163. sei ; Enable interrupts
  3164. sbr Flags0, (1<<OC1A_PENDING)
  3165. ret
  3166. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  3167. ;
  3168. ; Wait for commutation routine
  3169. ;
  3170. ; No assumptions
  3171. ;
  3172. ; Waits from zero cross to commutation
  3173. ;
  3174. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  3175. wait_for_comm:
  3176. ; Increment or reset consecutive count
  3177. lds XH, Demag_Consecutive_Cnt
  3178. inc XH
  3179. sts Demag_Consecutive_Cnt, XH
  3180. sbrs Flags0, DEMAG_DETECTED
  3181. sts Demag_Consecutive_Cnt, Zero
  3182. ; Check if a demag situation has occurred
  3183. sbrs Flags0, DEMAG_DETECTED ; Demag detected?
  3184. rjmp wait_for_comm_wait
  3185. ; Load programmed demag compensation
  3186. lds Temp3, Pgm_Demag_Comp_Power_Decoded ; Yes - load programmed demag compensation power decoded
  3187. ; Check for power off
  3188. cpi Temp3, 1
  3189. brne wait_for_comm_blind
  3190. sbr Flags0, (1<<DEMAG_CUT_POWER) ; Turn off motor power
  3191. All_nFETs_off XH
  3192. ; Wait a blind wait
  3193. wait_for_comm_blind:
  3194. rcall setup_zc_scan_wait ; Setup a zero cross scan wait (7.5 deg)
  3195. wait_demag_default_zc:
  3196. sbrc Flags0, OC1A_PENDING
  3197. rjmp wait_demag_default_zc
  3198. ; Check for power off
  3199. lds Temp3, Pgm_Demag_Comp_Power_Decoded ; Reload, since Temp3 is overwritten in setup_zc_scan_wait
  3200. cpi Temp3, 2
  3201. brne wait_for_comm_setup
  3202. sbr Flags0, (1<<DEMAG_CUT_POWER) ; Turn off motor power
  3203. All_nFETs_off XH
  3204. wait_for_comm_setup:
  3205. rcall setup_comm_wait ; Setup commutation wait
  3206. wait_for_comm_wait:
  3207. sbrc Flags0, OC1A_PENDING
  3208. rjmp wait_for_comm_wait
  3209. ret
  3210. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  3211. ;
  3212. ; Commutation routines
  3213. ;
  3214. ; No assumptions
  3215. ;
  3216. ; Performs commutation switching
  3217. ; Damped routines uses all pfets on when in pwm off to dampen the motor
  3218. ;
  3219. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  3220. comm1comm2:
  3221. cli ; Disable all interrupts
  3222. BpFET_off ; Bp off
  3223. sbrs Flags2, PGM_PWMOFF_DAMPED
  3224. rjmp comm12_nondamp
  3225. comm12_damp:
  3226. .IF DAMPED_MODE_ENABLE == 0
  3227. ldi ZL, low(pwm_cnfet_apfet_on_fast)
  3228. ldi ZH, high(pwm_cnfet_apfet_on_fast)
  3229. sbrc Flags2, PGM_PWMOFF_DAMPED_LIGHT
  3230. rjmp comm12_nondamp
  3231. .ENDIF
  3232. .IF DAMPED_MODE_ENABLE == 1
  3233. ldi ZL, low(pwm_cnfet_apfet_on_safe)
  3234. ldi ZH, high(pwm_cnfet_apfet_on_safe)
  3235. .ENDIF
  3236. sbrs Flags1, CURR_PWMOFF_DAMPED ; If pwm off not damped - branch
  3237. rjmp comm12_nondamp
  3238. CpFET_off
  3239. ldi XH, NFETON_DELAY ; Delay
  3240. dec XH
  3241. brne PC-1
  3242. comm12_nondamp:
  3243. .IF HIGH_DRIVER_PRECHG_TIME != 0 ; Precharge high side gate driver
  3244. AnFET_on
  3245. ldi XH, HIGH_DRIVER_PRECHG_TIME
  3246. dec XH
  3247. brne PC-1
  3248. AnFET_off
  3249. ldi XH, PFETON_DELAY
  3250. dec XH
  3251. brne PC-1
  3252. .ENDIF
  3253. ApFET_on ; Ap on
  3254. ldi XH, 2
  3255. sts Comm_Phase, XH
  3256. rjmp comm_exit
  3257. comm2comm3:
  3258. cli ; Disable all interrupts
  3259. sbrs Flags2, PGM_PWMOFF_DAMPED
  3260. rjmp comm23_nondamp
  3261. comm23_damp:
  3262. .IF DAMPED_MODE_ENABLE == 0
  3263. ldi ZL, low(pwm_bnfet_apfet_on_fast)
  3264. ldi ZH, high(pwm_bnfet_apfet_on_fast)
  3265. .ENDIF
  3266. .IF DAMPED_MODE_ENABLE == 1
  3267. ldi ZL, low(pwm_bnfet_apfet_on_safe)
  3268. ldi ZH, high(pwm_bnfet_apfet_on_safe)
  3269. .ENDIF
  3270. sbrs Flags1, CURR_PWMOFF_DAMPED ; If pwm off not damped - branch
  3271. rjmp comm23_nfet
  3272. BpFET_off
  3273. CpFET_off
  3274. ldi XH, NFETON_DELAY ; Delay
  3275. dec XH
  3276. brne PC-1
  3277. rjmp comm23_nfet
  3278. comm23_nondamp:
  3279. ldi ZL, low(pwm_bfet_on)
  3280. ldi ZH, high(pwm_bfet_on)
  3281. comm23_nfet:
  3282. CnFET_off ; Cn off
  3283. sbrs Flags0, PWM_ON ; Is pwm on?
  3284. rjmp comm23_cp
  3285. BnFET_on ; Yes - Bn on
  3286. comm23_cp:
  3287. ldi XH, 3
  3288. sts Comm_Phase, XH
  3289. rjmp comm_exit
  3290. comm3comm4:
  3291. cli ; Disable all interrupts
  3292. ApFET_off ; Ap off
  3293. sbrs Flags2, PGM_PWMOFF_DAMPED
  3294. rjmp comm34_nondamp
  3295. comm34_damp:
  3296. .IF DAMPED_MODE_ENABLE == 0
  3297. ldi ZL, low(pwm_bnfet_cpfet_on_fast)
  3298. ldi ZH, high(pwm_bnfet_cpfet_on_fast)
  3299. sbrc Flags2, PGM_PWMOFF_DAMPED_LIGHT
  3300. rjmp comm34_nondamp
  3301. .ENDIF
  3302. .IF DAMPED_MODE_ENABLE == 1
  3303. ldi ZL, low(pwm_bnfet_cpfet_on_safe)
  3304. ldi ZH, high(pwm_bnfet_cpfet_on_safe)
  3305. .ENDIF
  3306. sbrs Flags1, CURR_PWMOFF_DAMPED ; If pwm off not damped - branch
  3307. rjmp comm34_nondamp
  3308. BpFET_off
  3309. ldi XH, NFETON_DELAY ; Delay
  3310. dec XH
  3311. brne PC-1
  3312. comm34_nondamp:
  3313. .IF HIGH_DRIVER_PRECHG_TIME != 0 ; Precharge high side gate driver
  3314. CnFET_on
  3315. ldi XH, HIGH_DRIVER_PRECHG_TIME
  3316. dec XH
  3317. brne PC-1
  3318. CnFET_off
  3319. ldi XH, PFETON_DELAY
  3320. dec XH
  3321. brne PC-1
  3322. .ENDIF
  3323. CpFET_on ; Cp on
  3324. ldi XH, 4
  3325. sts Comm_Phase, XH
  3326. rjmp comm_exit
  3327. comm4comm5:
  3328. cli ; Disable all interrupts
  3329. sbrs Flags2, PGM_PWMOFF_DAMPED
  3330. rjmp comm45_nondamp
  3331. comm45_damp:
  3332. .IF DAMPED_MODE_ENABLE == 0
  3333. ldi ZL, low(pwm_anfet_cpfet_on_fast)
  3334. ldi ZH, high(pwm_anfet_cpfet_on_fast)
  3335. .ENDIF
  3336. .IF DAMPED_MODE_ENABLE == 1
  3337. ldi ZL, low(pwm_anfet_cpfet_on_safe)
  3338. ldi ZH, high(pwm_anfet_cpfet_on_safe)
  3339. .ENDIF
  3340. sbrs Flags1, CURR_PWMOFF_DAMPED ; If pwm off not damped - branch
  3341. rjmp comm45_nfet
  3342. ApFET_off
  3343. BpFET_off
  3344. ldi XH, NFETON_DELAY ; Delay
  3345. dec XH
  3346. brne PC-1
  3347. rjmp comm45_nfet
  3348. comm45_nondamp:
  3349. ldi ZL, low(pwm_afet_on)
  3350. ldi ZH, high(pwm_afet_on)
  3351. comm45_nfet:
  3352. BnFET_off ; Bn off
  3353. sbrs Flags0, PWM_ON ; Is pwm on?
  3354. rjmp comm45_cp
  3355. AnFET_on ; Yes - An on
  3356. comm45_cp:
  3357. ldi XH, 5
  3358. sts Comm_Phase, XH
  3359. rjmp comm_exit
  3360. comm5comm6:
  3361. cli ; Disable all interrupts
  3362. CpFET_off ; Cp off
  3363. sbrs Flags2, PGM_PWMOFF_DAMPED
  3364. rjmp comm56_nondamp
  3365. comm56_damp:
  3366. .IF DAMPED_MODE_ENABLE == 0
  3367. ldi ZL, low(pwm_anfet_bpfet_on_fast)
  3368. ldi ZH, high(pwm_anfet_bpfet_on_fast)
  3369. sbrc Flags2, PGM_PWMOFF_DAMPED_LIGHT
  3370. rjmp comm56_nondamp
  3371. .ENDIF
  3372. .IF DAMPED_MODE_ENABLE == 1
  3373. ldi ZL, low(pwm_anfet_bpfet_on_safe)
  3374. ldi ZH, high(pwm_anfet_bpfet_on_safe)
  3375. .ENDIF
  3376. sbrs Flags1, CURR_PWMOFF_DAMPED ; If pwm off not damped - branch
  3377. rjmp comm56_nondamp
  3378. ApFET_off
  3379. ldi XH, NFETON_DELAY ; Delay
  3380. dec XH
  3381. brne PC-1
  3382. comm56_nondamp:
  3383. .IF HIGH_DRIVER_PRECHG_TIME != 0 ; Precharge high side gate driver
  3384. BnFET_on
  3385. ldi XH, HIGH_DRIVER_PRECHG_TIME
  3386. dec XH
  3387. brne PC-1
  3388. BnFET_off
  3389. ldi XH, PFETON_DELAY
  3390. dec XH
  3391. brne PC-1
  3392. .ENDIF
  3393. BpFET_on ; Bp on
  3394. ldi XH, 6
  3395. sts Comm_Phase, XH
  3396. rjmp comm_exit
  3397. comm6comm1:
  3398. cli ; Disable all interrupts
  3399. sbrs Flags2, PGM_PWMOFF_DAMPED
  3400. rjmp comm61_nondamp
  3401. comm61_damp:
  3402. .IF DAMPED_MODE_ENABLE == 0
  3403. ldi ZL, low(pwm_cnfet_bpfet_on_fast)
  3404. ldi ZH, high(pwm_cnfet_bpfet_on_fast)
  3405. .ENDIF
  3406. .IF DAMPED_MODE_ENABLE == 1
  3407. ldi ZL, low(pwm_cnfet_bpfet_on_safe)
  3408. ldi ZH, high(pwm_cnfet_bpfet_on_safe)
  3409. .ENDIF
  3410. sbrs Flags1, CURR_PWMOFF_DAMPED ; If pwm off not damped - branch
  3411. rjmp comm61_nfet
  3412. ApFET_off
  3413. CpFET_off
  3414. ldi XH, NFETON_DELAY ; Delay
  3415. dec XH
  3416. brne PC-1
  3417. rjmp comm61_nfet
  3418. comm61_nondamp:
  3419. ldi ZL, low(pwm_cfet_on)
  3420. ldi ZH, high(pwm_cfet_on)
  3421. comm61_nfet:
  3422. AnFET_off ; An off
  3423. sbrs Flags0, PWM_ON ; Is pwm on?
  3424. rjmp comm61_cp
  3425. CnFET_on ; Yes - Cn on
  3426. comm61_cp:
  3427. ldi XH, 1
  3428. sts Comm_Phase, XH
  3429. comm_exit:
  3430. sei ; Enable all interrupts
  3431. lds XH, Pgm_Demag_Comp ; Check demag comp setting
  3432. cpi XH, 2 ; Check whether power shall be kept off upon consecutive demgs
  3433. brcs comm_restore_power ; Less than value - branch
  3434. lds XH, Demag_Consecutive_Cnt; Check consecutive demags
  3435. cpi XH, 3
  3436. brcc comm_return ; Do not reapply power if many consecutive demags. This will help retain sync during hard accelerations
  3437. comm_restore_power:
  3438. cbr Flags0, (1<<DEMAG_CUT_POWER) ; Clear demag power cut flag
  3439. comm_return:
  3440. ret
  3441. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  3442. ;
  3443. ; Switch power off routine
  3444. ;
  3445. ; No assumptions
  3446. ;
  3447. ; Switches all fets off
  3448. ;
  3449. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  3450. switch_power_off:
  3451. ldi Temp3, low(pwm_nofet_on) ; Set Z register to desired pwm_nfet_on label
  3452. ldi Temp4, high(pwm_nofet_on)
  3453. movw ZL, Temp3 ; Set Z register in one instruction
  3454. All_nFETs_Off XH ; Turn off all nfets
  3455. All_pFETs_Off XH ; Turn off all pfets
  3456. cbr Flags0, (1<<PWM_ON) ; Set pwm cycle to pwm off
  3457. ret
  3458. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  3459. ;
  3460. ; Set default parameters
  3461. ;
  3462. ; Assumes interrupt is disabled
  3463. ;
  3464. ; Sets default programming parameters
  3465. ;
  3466. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  3467. set_default_parameters:
  3468. .IF MODE == 0 ; Main
  3469. ldi XL, low(Pgm_Gov_P_Gain)
  3470. ldi XH, high(Pgm_Gov_P_Gain)
  3471. ldi Temp1, DEFAULT_PGM_MAIN_P_GAIN
  3472. st X+, Temp1
  3473. ldi Temp1, DEFAULT_PGM_MAIN_I_GAIN
  3474. st X+, Temp1
  3475. ldi Temp1, DEFAULT_PGM_MAIN_GOVERNOR_MODE
  3476. st X+, Temp1
  3477. ldi Temp1, DEFAULT_PGM_MAIN_LOW_VOLTAGE_LIM
  3478. st X+, Temp1
  3479. ldi Temp1, 0xFF
  3480. st X+, Temp1
  3481. st X+, Temp1
  3482. ldi Temp1, DEFAULT_PGM_MAIN_STARTUP_PWR
  3483. st X+, Temp1
  3484. ldi Temp1, DEFAULT_PGM_MAIN_PWM_FREQ
  3485. st X+, Temp1
  3486. ldi Temp1, DEFAULT_PGM_MAIN_DIRECTION
  3487. st X+, Temp1
  3488. ldi Temp1, DEFAULT_PGM_MAIN_RCP_PWM_POL
  3489. st X+, Temp1
  3490. ldi XL, low(Pgm_Enable_TX_Program)
  3491. ldi XH, high(Pgm_Enable_TX_Program)
  3492. ldi Temp1, DEFAULT_PGM_ENABLE_TX_PROGRAM
  3493. st X+, Temp1
  3494. ldi Temp1, DEFAULT_PGM_MAIN_REARM_START
  3495. st X+, Temp1
  3496. ldi Temp1, DEFAULT_PGM_MAIN_GOV_SETUP_TARGET
  3497. st X+, Temp1
  3498. ldi Temp1, 0xFF
  3499. st X+, Temp1
  3500. st X+, Temp1
  3501. st X+, Temp1
  3502. ldi Temp1, DEFAULT_PGM_MAIN_COMM_TIMING
  3503. st X+, Temp1
  3504. ldi Temp1, DEFAULT_PGM_MAIN_DAMPING_FORCE
  3505. st X+, Temp1
  3506. ldi Temp1, DEFAULT_PGM_MAIN_GOVERNOR_RANGE
  3507. st X+, Temp1
  3508. ldi Temp1, 0xFF
  3509. st X+, Temp1
  3510. ldi Temp1, DEFAULT_PGM_PPM_MIN_THROTTLE
  3511. st X+, Temp1
  3512. ldi Temp1, DEFAULT_PGM_PPM_MAX_THROTTLE
  3513. st X+, Temp1
  3514. ldi Temp1, DEFAULT_PGM_MAIN_BEEP_STRENGTH
  3515. st X+, Temp1
  3516. ldi Temp1, DEFAULT_PGM_MAIN_BEACON_STRENGTH
  3517. st X+, Temp1
  3518. ldi Temp1, DEFAULT_PGM_MAIN_BEACON_DELAY
  3519. st X+, Temp1
  3520. ldi Temp1, DEFAULT_PGM_MAIN_THROTTLE_RATE
  3521. st X+, Temp1
  3522. ldi Temp1, DEFAULT_PGM_MAIN_DEMAG_COMP
  3523. st X+, Temp1
  3524. ldi Temp1, DEFAULT_PGM_BEC_VOLTAGE_HIGH
  3525. st X+, Temp1
  3526. ldi Temp1, DEFAULT_PGM_PPM_CENTER_THROTTLE
  3527. st X+, Temp1
  3528. .ENDIF
  3529. .IF MODE == 1 ; Tail
  3530. ldi XL, low(Pgm_Gov_P_Gain)
  3531. ldi XH, high(Pgm_Gov_P_Gain)
  3532. ldi Temp1, 0xFF
  3533. st X+, Temp1
  3534. st X+, Temp1
  3535. st X+, Temp1
  3536. st X+, Temp1
  3537. ldi Temp1, DEFAULT_PGM_TAIL_GAIN
  3538. st X+, Temp1
  3539. ldi Temp1, DEFAULT_PGM_TAIL_IDLE_SPEED
  3540. st X+, Temp1
  3541. ldi Temp1, DEFAULT_PGM_TAIL_STARTUP_PWR
  3542. st X+, Temp1
  3543. ldi Temp1, DEFAULT_PGM_TAIL_PWM_FREQ
  3544. st X+, Temp1
  3545. ldi Temp1, DEFAULT_PGM_TAIL_DIRECTION
  3546. st X+, Temp1
  3547. ldi Temp1, DEFAULT_PGM_TAIL_RCP_PWM_POL
  3548. st X+, Temp1
  3549. ldi XL, low(Pgm_Enable_TX_Program)
  3550. ldi XH, high(Pgm_Enable_TX_Program)
  3551. ldi Temp1, DEFAULT_PGM_ENABLE_TX_PROGRAM
  3552. st X+, Temp1
  3553. ldi Temp1, 0xFF
  3554. st X+, Temp1
  3555. st X+, Temp1
  3556. ldi Temp1, 0xFF
  3557. st X+, Temp1
  3558. st X+, Temp1
  3559. st X+, Temp1
  3560. ldi Temp1, DEFAULT_PGM_TAIL_COMM_TIMING
  3561. st X+, Temp1
  3562. ldi Temp1, DEFAULT_PGM_TAIL_DAMPING_FORCE
  3563. st X+, Temp1
  3564. ldi Temp1, 0xFF
  3565. st X+, Temp1
  3566. st X+, Temp1
  3567. ldi Temp1, DEFAULT_PGM_PPM_MIN_THROTTLE
  3568. st X+, Temp1
  3569. ldi Temp1, DEFAULT_PGM_PPM_MAX_THROTTLE
  3570. st X+, Temp1
  3571. ldi Temp1, DEFAULT_PGM_TAIL_BEEP_STRENGTH
  3572. st X+, Temp1
  3573. ldi Temp1, DEFAULT_PGM_TAIL_BEACON_STRENGTH
  3574. st X+, Temp1
  3575. ldi Temp1, DEFAULT_PGM_TAIL_BEACON_DELAY
  3576. st X+, Temp1
  3577. ldi Temp1, DEFAULT_PGM_TAIL_THROTTLE_RATE
  3578. st X+, Temp1
  3579. ldi Temp1, DEFAULT_PGM_TAIL_DEMAG_COMP
  3580. st X+, Temp1
  3581. ldi Temp1, DEFAULT_PGM_BEC_VOLTAGE_HIGH
  3582. st X+, Temp1
  3583. ldi Temp1, DEFAULT_PGM_PPM_CENTER_THROTTLE
  3584. st X+, Temp1
  3585. .ENDIF
  3586. .IF MODE == 2 ; Multi
  3587. ldi XL, low(Pgm_Gov_P_Gain)
  3588. ldi XH, high(Pgm_Gov_P_Gain)
  3589. ldi Temp1, DEFAULT_PGM_MULTI_P_GAIN
  3590. st X+, Temp1
  3591. ldi Temp1, DEFAULT_PGM_MULTI_I_GAIN
  3592. st X+, Temp1
  3593. ldi Temp1, DEFAULT_PGM_MULTI_GOVERNOR_MODE
  3594. st X+, Temp1
  3595. ldi Temp1, DEFAULT_PGM_MULTI_LOW_VOLTAGE_LIM
  3596. st X+, Temp1
  3597. ldi Temp1, DEFAULT_PGM_MULTI_GAIN
  3598. st X+, Temp1
  3599. ldi Temp1, 0xFF
  3600. st X+, Temp1
  3601. ldi Temp1, DEFAULT_PGM_MULTI_STARTUP_PWR
  3602. st X+, Temp1
  3603. ldi Temp1, DEFAULT_PGM_MULTI_PWM_FREQ
  3604. st X+, Temp1
  3605. ldi Temp1, DEFAULT_PGM_MULTI_DIRECTION
  3606. st X+, Temp1
  3607. ldi Temp1, DEFAULT_PGM_MULTI_RCP_PWM_POL
  3608. st X+, Temp1
  3609. ldi XL, low(Pgm_Enable_TX_Program)
  3610. ldi XH, high(Pgm_Enable_TX_Program)
  3611. ldi Temp1, DEFAULT_PGM_ENABLE_TX_PROGRAM
  3612. st X+, Temp1
  3613. ldi Temp1, 0xFF
  3614. st X+, Temp1
  3615. st X+, Temp1
  3616. ldi Temp1, 0xFF
  3617. st X+, Temp1
  3618. st X+, Temp1
  3619. st X+, Temp1
  3620. ldi Temp1, DEFAULT_PGM_MULTI_COMM_TIMING
  3621. st X+, Temp1
  3622. ldi Temp1, DEFAULT_PGM_MULTI_DAMPING_FORCE
  3623. st X+, Temp1
  3624. ldi Temp1, 0xFF
  3625. st X+, Temp1
  3626. st X+, Temp1
  3627. ldi Temp1, DEFAULT_PGM_PPM_MIN_THROTTLE
  3628. st X+, Temp1
  3629. ldi Temp1, DEFAULT_PGM_PPM_MAX_THROTTLE
  3630. st X+, Temp1
  3631. ldi Temp1, DEFAULT_PGM_MULTI_BEEP_STRENGTH
  3632. st X+, Temp1
  3633. ldi Temp1, DEFAULT_PGM_MULTI_BEACON_STRENGTH
  3634. st X+, Temp1
  3635. ldi Temp1, DEFAULT_PGM_MULTI_BEACON_DELAY
  3636. st X+, Temp1
  3637. ldi Temp1, DEFAULT_PGM_MULTI_THROTTLE_RATE
  3638. st X+, Temp1
  3639. ldi Temp1, DEFAULT_PGM_MULTI_DEMAG_COMP
  3640. st X+, Temp1
  3641. ldi Temp1, DEFAULT_PGM_BEC_VOLTAGE_HIGH
  3642. st X+, Temp1
  3643. ldi Temp1, DEFAULT_PGM_PPM_CENTER_THROTTLE
  3644. st X+, Temp1
  3645. .ENDIF
  3646. ret
  3647. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  3648. ;
  3649. ; Decode parameters
  3650. ;
  3651. ; No assumptions
  3652. ;
  3653. ; Decodes programming parameters
  3654. ;
  3655. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  3656. decode_parameters:
  3657. ; Load programmed damping force
  3658. lds Temp3, Pgm_Damping_Force ; Load damping force and store in Temp3
  3659. ; Decode damping
  3660. ldi Temp1, 9 ; Set default
  3661. ldi Temp2, 1
  3662. cpi Temp3, 2
  3663. brne decode_damping_3 ; Look for 2
  3664. ldi Temp1, 5
  3665. ldi Temp2, 1
  3666. decode_damping_3:
  3667. cpi Temp3, 3
  3668. brne decode_damping_4 ; Look for 3
  3669. ldi Temp1, 5
  3670. ldi Temp2, 2
  3671. decode_damping_4:
  3672. cpi Temp3, 4
  3673. brne decode_damping_5 ; Look for 4
  3674. ldi Temp1, 5
  3675. ldi Temp2, 3
  3676. decode_damping_5:
  3677. cpi Temp3, 5
  3678. brne decode_damping_6 ; Look for 5
  3679. ldi Temp1, 9
  3680. ldi Temp2, 7
  3681. decode_damping_6:
  3682. cpi Temp3, 6
  3683. brne decode_damping_done ; Look for 6
  3684. ldi Temp1, 0
  3685. ldi Temp2, 0
  3686. decode_damping_done:
  3687. sts Damping_Period, Temp1
  3688. sts Damping_On, Temp2
  3689. ; Load programmed pwm frequency
  3690. lds Temp3, Pgm_Pwm_Freq ; Load pwm freq and store in Temp3
  3691. .IF MODE == 0 ; Main
  3692. cbr Flags2, (1<<PGM_PWMOFF_DAMPED_LIGHT)
  3693. cpi Temp3, 3
  3694. brne PC+2
  3695. sbr Flags2, (1<<PGM_PWMOFF_DAMPED_LIGHT)
  3696. cbr Flags2, (1<<PGM_PWMOFF_DAMPED_FULL)
  3697. .ENDIF
  3698. .IF MODE >= 1 ; Tail or multi
  3699. cbr Flags2, (1<<PGM_PWMOFF_DAMPED_LIGHT)
  3700. cpi Temp3, 3
  3701. brne PC+2
  3702. sbr Flags2, (1<<PGM_PWMOFF_DAMPED_LIGHT)
  3703. cbr Flags2, (1<<PGM_PWMOFF_DAMPED_FULL)
  3704. cpi Temp3, 4
  3705. brne PC+2
  3706. sbr Flags2, (1<<PGM_PWMOFF_DAMPED_FULL)
  3707. .ENDIF
  3708. cbr Flags2, (1<<PGM_PWMOFF_DAMPED) ; Set damped flag if fully damped or damped light is set
  3709. ldi XH, ((1<<PGM_PWMOFF_DAMPED_FULL)+(1<<PGM_PWMOFF_DAMPED_LIGHT))
  3710. and XH, Flags2 ; Check if any damped mode is set
  3711. breq PC+2
  3712. sbr Flags2, (1<<PGM_PWMOFF_DAMPED)
  3713. cbr Flags1, (1<<CURR_PWMOFF_DAMPED) ; Set non damped status as start
  3714. tst XH
  3715. breq PC+2
  3716. sbr Flags1, (1<<CURR_PWMOFF_DAMPED) ; Set non damped status as start if damped
  3717. sbr Flags1, (1<<CURR_PWMOFF_COMP_ABLE) ; Set comparator usable status
  3718. tst XH
  3719. breq PC+2
  3720. cbr Flags1, (1<<CURR_PWMOFF_COMP_ABLE) ; Set comparator not usable status if damped
  3721. ; Load programmed direction
  3722. lds XH, Pgm_Direction
  3723. .IF MODE >= 1 ; Tail or multi
  3724. cpi XH, 3
  3725. breq decode_params_dir_set
  3726. .ENDIF
  3727. cbr Flags3, (1<<PGM_DIR_REV)
  3728. sbrc XH, 1
  3729. sbr Flags3, (1<<PGM_DIR_REV)
  3730. decode_params_dir_set:
  3731. cbr Flags3, (1<<PGM_RCP_PWM_POL)
  3732. lds XH, Pgm_Input_Pol
  3733. sbrc XH, 1
  3734. sbr Flags3, (1<<PGM_RCP_PWM_POL)
  3735. mov XH, Temp3
  3736. cpi XH, 2
  3737. breq decode_pwm_freq_low
  3738. sbr Flags2, (1<<PGM_PWM_HIGH_FREQ)
  3739. rjmp decode_pwm_freq_end
  3740. decode_pwm_freq_low:
  3741. cbr Flags2, (1<<PGM_PWM_HIGH_FREQ)
  3742. decode_pwm_freq_end:
  3743. ret
  3744. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  3745. ;
  3746. ; Decode governor gain
  3747. ;
  3748. ; No assumptions
  3749. ;
  3750. ; Decodes governor gains
  3751. ;
  3752. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  3753. decode_governor_gains:
  3754. ; Decode governor gains
  3755. ldi ZL, low(GOV_GAIN_TABLE<<1)
  3756. ldi ZH, high(GOV_GAIN_TABLE<<1)
  3757. lds Temp1, Pgm_Gov_P_Gain ; Decode governor P gain
  3758. dec Temp1
  3759. add ZL, Temp1
  3760. adc ZH, Zero
  3761. lpm XH, Z
  3762. sts Pgm_Gov_P_Gain_Decoded, XH
  3763. lds Temp1, Pgm_Gov_I_Gain ; Decode governor I gain
  3764. dec Temp1
  3765. add ZL, Temp1
  3766. adc ZH, Zero
  3767. lpm XH, Z
  3768. sts Pgm_Gov_I_Gain_Decoded, XH
  3769. rcall switch_power_off ; Reset Z register
  3770. ret
  3771. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  3772. ;
  3773. ; Decode throttle rate
  3774. ;
  3775. ; No assumptions
  3776. ;
  3777. ; Decodes throttle rate
  3778. ;
  3779. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  3780. decode_throttle_rate:
  3781. ; Decode throttle rate
  3782. ldi ZL, low(THROTTLE_RATE_TABLE<<1)
  3783. ldi ZH, high(THROTTLE_RATE_TABLE<<1)
  3784. lds Temp1, Pgm_Throttle_Rate
  3785. dec Temp1
  3786. add ZL, Temp1
  3787. adc ZH, Zero
  3788. lpm XH, Z
  3789. sts Pgm_Throttle_Rate_Decoded, XH
  3790. rcall switch_power_off ; Reset Z register
  3791. ret
  3792. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  3793. ;
  3794. ; Decode startup power
  3795. ;
  3796. ; No assumptions
  3797. ;
  3798. ; Decodes startup power
  3799. ;
  3800. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  3801. decode_startup_power:
  3802. ; Decode startup power
  3803. ldi ZL, low(STARTUP_POWER_TABLE<<1)
  3804. ldi ZH, high(STARTUP_POWER_TABLE<<1)
  3805. lds Temp1, Pgm_Startup_Pwr
  3806. dec Temp1
  3807. add ZL, Temp1
  3808. adc ZH, Zero
  3809. lpm XH, Z
  3810. sts Pgm_Startup_Pwr_Decoded, XH
  3811. rcall switch_power_off ; Reset Z register
  3812. ret
  3813. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  3814. ;
  3815. ; Decode demag compensation
  3816. ;
  3817. ; No assumptions
  3818. ;
  3819. ; Decodes throttle rate
  3820. ;
  3821. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  3822. decode_demag_comp:
  3823. ; Decode demag compensation
  3824. ldi ZL, low(DEMAG_POWER_TABLE<<1)
  3825. ldi ZH, high(DEMAG_POWER_TABLE<<1)
  3826. lds Temp1, Pgm_Demag_Comp
  3827. dec Temp1
  3828. add ZL, Temp1
  3829. adc ZH, Zero
  3830. lpm XH, Z
  3831. sts Pgm_Demag_Comp_Power_Decoded, XH
  3832. rcall switch_power_off ; Reset Z register
  3833. ret
  3834. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  3835. ;
  3836. ; Set BEC voltage
  3837. ;
  3838. ; No assumptions
  3839. ;
  3840. ; Sets the BEC output voltage low or high
  3841. ;
  3842. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  3843. set_bec_voltage:
  3844. ; Set bec voltage
  3845. .IF DUAL_BEC_VOLTAGE == 1
  3846. Set_BEC_Lo XH ; Set default to low
  3847. lds Temp1, Pgm_BEC_Voltage_High
  3848. tst Temp1
  3849. breq set_bec_voltage_exit
  3850. Set_BEC_Hi XH ; Set to high
  3851. set_bec_voltage_exit:
  3852. .ENDIF
  3853. ret
  3854. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  3855. ;
  3856. ; Find throttle gain
  3857. ;
  3858. ; Assumes that interrupts are disabled
  3859. ; Assumes that the difference between max and min throttle must be more than 520us (a Pgm_Ppm_xxx_Throttle difference of 130)
  3860. ;
  3861. ; Finds throttle gain from throttle calibration values
  3862. ;
  3863. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  3864. find_throttle_gain:
  3865. ; Load programmed minimum and maximum throttle
  3866. lds Temp3, Pgm_Ppm_Min_Throttle
  3867. lds Temp4, Pgm_Ppm_Max_Throttle
  3868. ; Check if full range is chosen
  3869. sbrs Flags3, FULL_THROTTLE_RANGE
  3870. rjmp find_throttle_gain_calculate
  3871. ldi Temp3, 0
  3872. ldi Temp4, 255
  3873. find_throttle_gain_calculate:
  3874. ; Calculate difference
  3875. mov XH, Temp4
  3876. sub XH, Temp3
  3877. mov Temp5, XH
  3878. ; Check that difference is minimum 130
  3879. subi XH, 130
  3880. brcc PC+3
  3881. ldi XH, 130
  3882. mov Temp5, XH
  3883. ; Find gain
  3884. ldi Temp1, 0
  3885. test_throttle_gain:
  3886. inc Temp1
  3887. mul Temp5, Temp1 ; Temp5 has difference, Temp1 has gain
  3888. mov XH, Mul_Res_H
  3889. subi XH, 128
  3890. brcs test_throttle_gain
  3891. sts Ppm_Throttle_Gain, Temp1 ; Store gain
  3892. ret
  3893. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  3894. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  3895. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  3896. ;
  3897. ; Main program start
  3898. ;
  3899. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  3900. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  3901. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  3902. reset:
  3903. ; Disable interrupts explicitly
  3904. cli
  3905. ; Check lock bits
  3906. ldi ZL, 0x01
  3907. ldi ZH, 0x00
  3908. Prepare_Lock_Or_Fuse_Read XH
  3909. lpm XH, Z
  3910. cpi XH, 0xFF
  3911. brne reset ; If lock bits byte is not 0xFF, then loop here
  3912. ; Check fuse high bits
  3913. ldi ZL, 0x03
  3914. ldi ZH, 0x00
  3915. Prepare_Lock_Or_Fuse_Read XH
  3916. lpm XH, Z
  3917. andi XH, 0x80
  3918. breq reset ; If RSTDISBL is programmed, then loop here
  3919. ; Disable watchdog
  3920. Disable_Watchdog XH
  3921. ; Initialize MCU
  3922. Initialize_MCU XH
  3923. ; Initialize stack
  3924. ldi XH, high(RAMEND) ; Stack = RAMEND
  3925. out SPH, XH
  3926. ldi XH, low(RAMEND)
  3927. out SPL, XH
  3928. ; Switch power off
  3929. rcall switch_power_off
  3930. ; PortB initialization
  3931. ldi XH, INIT_PB
  3932. out PORTB, XH
  3933. ldi XH, DIR_PB
  3934. out DDRB, XH
  3935. ; PortC initialization
  3936. ldi XH, INIT_PC
  3937. out PORTC, XH
  3938. ldi XH, DIR_PC
  3939. out DDRC, XH
  3940. ; PortD initialization
  3941. ldi XH, INIT_PD
  3942. out PORTD, XH
  3943. ldi XH, DIR_PD
  3944. out DDRD, XH
  3945. ; Clear registers r0 through r25
  3946. clr Zero
  3947. ldi XL, low(0) ; Register number
  3948. ldi XH, low(0)
  3949. clear_regs:
  3950. st X+, Zero ; Clear register and post increment register number
  3951. cpi XL, 26 ; Check register number - last register?
  3952. brne clear_regs ; If not last register, go back
  3953. ; Clear RAM
  3954. ldi XL, low(SRAM_START)
  3955. ldi XH, high(SRAM_START)
  3956. ldi Temp1, SRAM_BYTES
  3957. clear_ram:
  3958. st X+, Zero
  3959. dec Temp1
  3960. brne clear_ram
  3961. ; Set default programmed parameters
  3962. rcall set_default_parameters
  3963. ; Read all programmed parameters
  3964. rcall read_all_eeprom_parameters
  3965. ; Decode parameters
  3966. rcall decode_parameters
  3967. ; Decode governor gains
  3968. rcall decode_governor_gains
  3969. ; Decode throttle rate
  3970. rcall decode_throttle_rate
  3971. ; Decode startup power
  3972. rcall decode_startup_power
  3973. ; Decode demag compensation
  3974. rcall decode_demag_comp
  3975. ; Set BEC voltage
  3976. rcall set_bec_voltage
  3977. ; Find throttle gain from stored min and max settings
  3978. rcall find_throttle_gain
  3979. ; Set beep strength
  3980. lds Temp1, Pgm_Beep_Strength
  3981. sts Beep_Strength, Temp1
  3982. ; Switch power off
  3983. rcall switch_power_off
  3984. ; Timer0: clk/8 for regular interrupts
  3985. ldi XH, (1<<CS01)
  3986. Set_Timer0_CS0 XH
  3987. ; Timer1: clk/8 for commutation control and RC pulse measurement
  3988. ldi XH, (1<<CS11)
  3989. Set_Timer1_CS1 XH
  3990. ; Timer2: clk/8 for pwm
  3991. ldi XH, (1<<CS21)
  3992. Set_Timer2_CS2 XH
  3993. ; Initializing beep
  3994. cli ; Disable interrupts explicitly
  3995. rcall wait200ms
  3996. rcall beep_f1
  3997. rcall wait30ms
  3998. rcall beep_f2
  3999. rcall wait30ms
  4000. rcall beep_f3
  4001. rcall wait30ms
  4002. ; Wait for receiver to initialize
  4003. rcall wait1s
  4004. rcall wait200ms
  4005. rcall wait200ms
  4006. rcall wait100ms
  4007. ; Initialize interrupts and registers
  4008. Initialize_Interrupts XH ; Set all interrupt enable bits
  4009. ; Initialize comparator
  4010. Comp_Init XH ; Initialize comparator
  4011. ; Initialize ADC
  4012. Initialize_Adc XH ; Initialize ADC operation
  4013. rcall wait1ms
  4014. sei ; Enable all interrupts
  4015. ; Measure number of lipo cells
  4016. rcall Measure_Lipo_Cells ; Measure number of lipo cells
  4017. ; Initialize RC pulse
  4018. Rcp_Int_Enable XH ; Enable interrupt
  4019. Rcp_Clear_Int_Flag XH ; Clear interrupt flag
  4020. cbr Flags2, (1<<RCP_EDGE_NO) ; Set first edge flag
  4021. rcall wait200ms
  4022. ; Set initial arm variable
  4023. ldi XH, 1
  4024. sts Initial_Arm, XH
  4025. ; Measure PWM frequency
  4026. measure_pwm_freq_init:
  4027. sbr Flags0, (1<<RCP_MEAS_PWM_FREQ) ; Set measure pwm frequency flag
  4028. measure_pwm_freq_start:
  4029. ldi Temp3, 5 ; Number of pulses to measure
  4030. measure_pwm_freq_loop:
  4031. ; Check if period diff was accepted
  4032. lds XH, Rcp_Period_Diff_Accepted
  4033. tst XH
  4034. brne PC+2
  4035. ldi Temp3, 5 ; Reset number of pulses to measure
  4036. rcall wait3ms ; Wait for next pulse (NB: Uses Temp1/2!)
  4037. lds XH, New_Rcp ; Load value
  4038. cpi XH, RCP_VALIDATE ; Higher than validate level?
  4039. brcs measure_pwm_freq_start ; No - start over
  4040. mov XH, Flags3 ; Check pwm frequency flags
  4041. andi XH, ((1<<RCP_PWM_FREQ_1KHZ)+(1<<RCP_PWM_FREQ_2KHZ)+(1<<RCP_PWM_FREQ_4KHZ)+(1<<RCP_PWM_FREQ_8KHZ)+(1<<RCP_PWM_FREQ_12KHZ))
  4042. lds Temp1, Curr_Rcp_Pwm_Freq ; Store as previous flags for next pulse
  4043. sts Prev_Rcp_Pwm_Freq, Temp1
  4044. sts Curr_Rcp_Pwm_Freq, XH ; Store current flags for next pulse
  4045. cp XH, Temp1
  4046. brne measure_pwm_freq_start ; Go back if new flags not same as previous
  4047. dec Temp3
  4048. brne measure_pwm_freq_loop ; Go back if not required number of pulses seen
  4049. ; Clear measure pwm frequency flag
  4050. cbr Flags0, (1<<RCP_MEAS_PWM_FREQ)
  4051. ; Set up RC pulse interrupts after pwm frequency measurement
  4052. Rcp_Int_First XH ; Enable interrupt and set to first edge
  4053. Rcp_Clear_Int_Flag XH ; Clear interrupt flag
  4054. cbr Flags2, (1<<RCP_EDGE_NO) ; Set first edge flag
  4055. rcall wait100ms ; Wait for new RC pulse
  4056. ; Validate RC pulse
  4057. validate_rcp_start:
  4058. rcall wait3ms ; Wait for next pulse (NB: Uses Temp1/2!)
  4059. ldi Temp1, RCP_VALIDATE ; Set validate level as default
  4060. mov XH, Flags3 ; Check pwm frequency flags
  4061. andi XH, ((1<<RCP_PWM_FREQ_1KHZ)+(1<<RCP_PWM_FREQ_2KHZ)+(1<<RCP_PWM_FREQ_4KHZ)+(1<<RCP_PWM_FREQ_8KHZ)+(1<<RCP_PWM_FREQ_12KHZ))
  4062. brne PC+2 ; If a flag is set (PWM) - branch
  4063. ldi Temp1, 0 ; Set level to zero for PPM (any level will be accepted)
  4064. lds XH, New_Rcp ; Load value
  4065. cp XH, Temp1 ; Higher than validate level?
  4066. brcs validate_rcp_start ; No - start over
  4067. ; Beep arm sequence start signal
  4068. cli ; Disable all interrupts
  4069. rcall beep_f1 ; Signal that RC pulse is ready
  4070. rcall beep_f1
  4071. rcall beep_f1
  4072. sei ; Enable all interrupts
  4073. rcall wait200ms
  4074. ; Arming sequence start
  4075. sts Gov_Arm_Target, Zero ; Clear governor arm target
  4076. arming_start:
  4077. .IF MODE >= 1 ; Tail or multi
  4078. lds XH, Pgm_Direction ; Check if bidirectional operation
  4079. cpi XH, 3
  4080. brne PC+2
  4081. rjmp program_by_tx_checked ; Disable tx programming if bidirectional operation
  4082. .ENDIF
  4083. rcall wait3ms
  4084. lds XH, Pgm_Enable_TX_Program; Start programming mode entry if enabled
  4085. cpi XH, 1 ; Is TX programming enabled?
  4086. brcc arming_initial_arm_check ; Yes - proceed
  4087. rjmp program_by_tx_checked ; No - branch
  4088. arming_initial_arm_check:
  4089. lds XH, Initial_Arm ; Yes - check if it is initial arm sequence
  4090. cpi XH, 1 ; Is it the initial arm sequence?
  4091. brcc arming_ppm_check ; Yes - proceed
  4092. rjmp program_by_tx_checked ; No - branch
  4093. arming_ppm_check:
  4094. mov XH, Flags3 ; Check pwm frequency flags
  4095. andi XH, ((1<<RCP_PWM_FREQ_1KHZ)+(1<<RCP_PWM_FREQ_2KHZ)+(1<<RCP_PWM_FREQ_4KHZ)+(1<<RCP_PWM_FREQ_8KHZ)+(1<<RCP_PWM_FREQ_12KHZ))
  4096. breq throttle_high_cal_start ; If no flag is set (PPM) - branch
  4097. ; PWM tx program entry
  4098. lds XH, New_Rcp ; Load new RC pulse value
  4099. cpi XH, RCP_MAX ; Is RC pulse max?
  4100. brcc program_by_tx_entry_pwm ; Yes - proceed
  4101. rjmp program_by_tx_checked ; No - branch
  4102. program_by_tx_entry_pwm:
  4103. cli ; Disable all interrupts
  4104. rcall beep_f4
  4105. sei ; Enable all interrupts
  4106. rcall wait100ms
  4107. lds XH, New_Rcp ; Load new RC pulse value
  4108. cpi XH, RCP_STOP ; Below stop?
  4109. brcc program_by_tx_entry_pwm ; No - start over
  4110. program_by_tx_entry_wait_pwm:
  4111. cli ; Disable all interrupts
  4112. rcall beep_f1
  4113. rcall wait10ms
  4114. rcall beep_f1
  4115. sei ; Enable all interrupts
  4116. rcall wait100ms
  4117. lds XH, New_Rcp ; Load new RC pulse value
  4118. cpi XH, RCP_MAX ; At or above max?
  4119. brcs program_by_tx_entry_wait_pwm ; No - start over
  4120. rjmp program_by_tx ; Yes - enter programming mode
  4121. ; PPM throttle calibration and tx program entry
  4122. throttle_high_cal_start:
  4123. ldi XH, 8 ; Set 3 seconds wait time
  4124. mov Temp8, XH
  4125. throttle_high_cal:
  4126. sbr Flags3, (1<<FULL_THROTTLE_RANGE) ; Set range to 1000-2020us
  4127. cli
  4128. rcall find_throttle_gain ; Set throttle gain
  4129. sei
  4130. rcall wait100ms ; Wait for new throttle value
  4131. cli ; Disable interrupts (freeze New_Rcp value)
  4132. cbr Flags3, (1<<FULL_THROTTLE_RANGE) ; Set programmed range
  4133. rcall find_throttle_gain ; Set throttle gain
  4134. lds Temp7, New_Rcp ; Store new RC pulse value
  4135. lds XH, New_Rcp ; Load new RC pulse value
  4136. cpi XH, (RCP_MAX/2) ; Is RC pulse above midstick?
  4137. sei ; Enable interrupts
  4138. brcc PC+2
  4139. rjmp arm_target_updated ; No - branch
  4140. rcall wait1ms
  4141. cli ; Disable all interrupts
  4142. rcall beep_f4
  4143. sei ; Enable all interrupts
  4144. dec Temp8
  4145. brne throttle_high_cal ; Continue to wait
  4146. mov XH, Temp7 ; Limit to max 250
  4147. subi XH, 5 ; Subtract about 2% and ensure that it is 250 or lower
  4148. sts Pgm_Ppm_Max_Throttle, XH ; Store
  4149. rcall wait200ms
  4150. cli
  4151. rcall store_all_in_eeprom
  4152. rcall success_beep
  4153. sei
  4154. throttle_low_cal_start:
  4155. ldi XH, 10 ; Set 3 seconds wait time
  4156. mov Temp8, XH
  4157. throttle_low_cal:
  4158. sbr Flags3, (1<<FULL_THROTTLE_RANGE) ; Set range to 1000-2020us
  4159. cli
  4160. rcall find_throttle_gain ; Set throttle gain
  4161. sei
  4162. rcall wait100ms
  4163. cli ; Disable interrupts (freeze New_Rcp value)
  4164. cbr Flags3, (1<<FULL_THROTTLE_RANGE) ; Set programmed range
  4165. rcall find_throttle_gain ; Set throttle gain
  4166. lds Temp7, New_Rcp ; Store new RC pulse value
  4167. lds XH, New_Rcp ; Load new RC pulse value
  4168. cpi XH, (RCP_MAX/2) ; Below midstick?
  4169. sei ; Enable interrupts
  4170. brcc throttle_low_cal_start ; No - start over
  4171. rcall wait1ms
  4172. cli ; Disable all interrupts
  4173. rcall beep_f1
  4174. rcall wait10ms
  4175. rcall beep_f1
  4176. sei ; Enable all interrupts
  4177. dec Temp8
  4178. brne throttle_low_cal ; Continue to wait
  4179. mov XH, Temp7
  4180. subi XH, 0xFB ; Add about 2% (subtract negative number)
  4181. sts Pgm_Ppm_Min_Throttle, XH ; Store
  4182. rcall wait200ms
  4183. cli
  4184. rcall store_all_in_eeprom
  4185. rcall success_beep_inverted
  4186. sei
  4187. program_by_tx_entry_wait_ppm:
  4188. rcall wait100ms
  4189. cli
  4190. rcall find_throttle_gain ; Set throttle gain
  4191. sei
  4192. lds XH, New_Rcp ; Load new RC pulse value
  4193. cpi XH, RCP_MAX ; At or above max?
  4194. brcs program_by_tx_entry_wait_ppm ; No - start over
  4195. rjmp program_by_tx ; Yes - enter programming mode
  4196. program_by_tx_checked:
  4197. lds Temp1, New_Rcp ; Load new RC pulse value
  4198. lds XH, Gov_Arm_Target ; Is RC pulse larger than arm target?
  4199. cp Temp1, XH
  4200. brcs arm_target_updated ; No - do not update
  4201. sts Gov_Arm_Target, Temp1 ; Yes - update arm target
  4202. arm_target_updated:
  4203. rcall wait100ms ; Wait for new throttle value
  4204. lds XH, New_Rcp ; Load new RC pulse value
  4205. cpi XH, RCP_STOP ; Below stop?
  4206. brcs arm_end_beep ; Yes - proceed
  4207. rjmp arming_start ; No - start over
  4208. arm_end_beep:
  4209. ; Beep arm sequence end signal
  4210. cli ; Disable all interrupts
  4211. rcall beep_f4 ; Signal that rcpulse is ready
  4212. rcall beep_f4
  4213. rcall beep_f4
  4214. sei ; Enable all interrupts
  4215. rcall wait200ms
  4216. ; Clear initial arm variable
  4217. sts Initial_Arm, Zero
  4218. ; Armed and waiting for power on
  4219. wait_for_power_on:
  4220. sts Power_On_Wait_Cnt_L, Zero; Clear wait counter
  4221. sts Power_On_Wait_Cnt_H, Zero
  4222. wait_for_power_on_loop:
  4223. lds XH, Power_On_Wait_Cnt_L ; Increment low wait counter
  4224. inc XH
  4225. sts Power_On_Wait_Cnt_L, XH
  4226. cpi XH, 0xFF
  4227. brne wait_for_power_on_no_beep; Counter wrapping (about 1 sec)?
  4228. lds XH, Power_On_Wait_Cnt_H ; Increment high wait counter
  4229. inc XH
  4230. sts Power_On_Wait_Cnt_H, XH
  4231. lds XH, Pgm_Beacon_Delay
  4232. ldi Temp1, 25 ; Approximately 1 min
  4233. dec XH
  4234. breq beep_delay_set
  4235. ldi Temp1, 50 ; Approximately 2 min
  4236. dec XH
  4237. breq beep_delay_set
  4238. ldi Temp1, 125 ; Approximately 5 min
  4239. dec XH
  4240. breq beep_delay_set
  4241. ldi Temp1, 250 ; Approximately 10 min
  4242. dec XH
  4243. breq beep_delay_set
  4244. sts Power_On_Wait_Cnt_H, Zero; Reset counter for infinite delay
  4245. beep_delay_set:
  4246. lds XH, Power_On_Wait_Cnt_H
  4247. cp XH, Temp1 ; Check against chosen delay
  4248. brcs wait_for_power_on_no_beep; Has delay elapsed?
  4249. lds XH, Power_On_Wait_Cnt_H ; Decrement high wait counter
  4250. dec XH
  4251. sts Power_On_Wait_Cnt_H, XH
  4252. ldi XH, 180 ; Set low wait counter
  4253. sts Power_On_Wait_Cnt_L, XH
  4254. lds XH, Pgm_Beacon_Strength
  4255. sts Beep_Strength, XH
  4256. cli ; Disable all interrupts
  4257. rcall beep_f4 ; Signal that there is no signal
  4258. sei ; Enable all interrupts
  4259. lds XH, Pgm_Beep_Strength
  4260. sts Beep_Strength, XH
  4261. rcall wait100ms ; Wait for new RC pulse to be measured
  4262. wait_for_power_on_no_beep:
  4263. rcall wait10ms
  4264. lds XH, Rcp_Timeout_Cnt ; Load RC pulse timeout counter value
  4265. tst XH
  4266. brne wait_for_power_on_ppm_not_missing ; If it is not zero - proceed
  4267. mov XH, Flags3 ; Check pwm frequency flags
  4268. andi XH, ((1<<RCP_PWM_FREQ_1KHZ)+(1<<RCP_PWM_FREQ_2KHZ)+(1<<RCP_PWM_FREQ_4KHZ)+(1<<RCP_PWM_FREQ_8KHZ)+(1<<RCP_PWM_FREQ_12KHZ))
  4269. brne wait_for_power_on_ppm_not_missing ; If a flag is set (PWM) - branch
  4270. rjmp measure_pwm_freq_init ; If ppm and pulses missing - go back to measure pwm frequency
  4271. wait_for_power_on_ppm_not_missing:
  4272. lds XH, New_Rcp ; Load new RC pulse value
  4273. cpi XH, (RCP_STOP+5) ; Higher than stop (plus some hysteresis)?
  4274. brcc PC+2
  4275. rjmp wait_for_power_on_loop ; No - start over
  4276. .IF MODE >= 1 ; Tail or multi
  4277. lds XH, Pgm_Direction ; Check if bidirectional operation
  4278. subi XH, 3
  4279. breq PC+2 ; Do not wait if bidirectional operation
  4280. .ENDIF
  4281. rcall wait100ms ; Wait to see if start pulse was only a glitch
  4282. lds XH, Rcp_Timeout_Cnt ; Load RC pulse timeout counter value
  4283. tst XH
  4284. brne PC+2 ; If it is not zero - proceed
  4285. rjmp measure_pwm_freq_init ; If it is zero (pulses missing) - go back to measure pwm frequency
  4286. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  4287. ;
  4288. ; Start entry point
  4289. ;
  4290. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  4291. init_start:
  4292. cli
  4293. rcall switch_power_off
  4294. sts Requested_Pwm, Zero ; Set requested pwm to zero
  4295. sts Governor_Req_Pwm, Zero ; Set governor requested pwm to zero
  4296. sts Current_Pwm, Zero ; Set current pwm to zero
  4297. mov Current_Pwm_Limited, Zero; Set limited current pwm to zero
  4298. sei
  4299. lds XH, Pgm_Motor_Idle
  4300. sts Pwm_Motor_Idle, XH ; Set idle pwm to programmed value
  4301. sts Gov_Target_L, Zero ; Set target to zero
  4302. sts Gov_Target_H, Zero
  4303. sts Gov_Integral_L, Zero ; Set integral to zero
  4304. sts Gov_Integral_H, Zero
  4305. sts Gov_Integral_X, Zero
  4306. sts Adc_Conversion_Cnt, Zero
  4307. ldi Flags0, 0 ; Clear flags0
  4308. ldi Flags1, 0 ; Clear flags1
  4309. sts Demag_Consecutive_Cnt, Zero
  4310. rcall initialize_all_timings ; Initialize timing
  4311. ;**** **** **** **** ****
  4312. ; Motor start beginning
  4313. ;**** **** **** **** ****
  4314. ldi XH, TEMP_CHECK_RATE ; Make sure a temp reading is done
  4315. sts Adc_Conversion_Cnt, XH
  4316. Set_Adc_Ip_Temp
  4317. rcall wait1ms
  4318. Start_Adc XH
  4319. read_initial_temp:
  4320. Get_Adc_Status XH
  4321. sbrc XH, ADSC
  4322. rjmp read_initial_temp
  4323. Read_Adc_Result Temp1, Temp2 ; Read initial temperature
  4324. Stop_Adc XH
  4325. tst Temp2
  4326. breq PC+2 ; Is reading below 256?
  4327. ldi Temp1, 0xFF ; No - set average temperature value to 255
  4328. sts Current_Average_Temp_Adc, Temp1 ; Set initial average temp ADC reading
  4329. rcall check_temp_voltage_and_limit_power
  4330. ldi XH, TEMP_CHECK_RATE ; Make sure a temp reading is done next time
  4331. sts Adc_Conversion_Cnt, XH
  4332. Set_Adc_Ip_Temp
  4333. ; Set up start operating conditions
  4334. lds Temp7, Pgm_Pwm_Freq ; Store setting in Temp7
  4335. ldi XH, 2 ; Set nondamped low frequency pwm mode
  4336. sts Pgm_Pwm_Freq, XH
  4337. rcall decode_parameters ; (Decode_parameters uses Temp1 and Temp8)
  4338. sts Pgm_Pwm_Freq, Temp7 ; Restore settings
  4339. ; Set max allowed power
  4340. cli ; Disable interrupts to avoid that Requested_Pwm is overwritten
  4341. ldi XH, 0xFF ; Set pwm limit to max
  4342. sts Pwm_Limit, XH
  4343. rcall set_startup_pwm
  4344. lds XH, Requested_Pwm
  4345. sts Pwm_Limit, XH
  4346. sts Pwm_Limit_Spoolup, XH
  4347. sei
  4348. ldi XH, 1 ; Set low pwm again after calling set_startup_pwm
  4349. mov Current_Pwm_Limited, XH
  4350. sts Spoolup_Limit_Skip, XH
  4351. lds XH, Auto_Bailout_Armed
  4352. sts Spoolup_Limit_Cnt, XH
  4353. ; Begin startup sequence
  4354. sbr Flags1, (1<<MOTOR_SPINNING) ; Set motor spinning flag
  4355. sbr Flags1, (1<<STARTUP_PHASE) ; Set startup phase flag
  4356. sts Startup_Ok_Cnt, Zero ; Reset ok counter
  4357. rcall comm5comm6 ; Initialize commutation
  4358. rcall comm6comm1
  4359. rcall calc_next_comm_timing ; Set virtual commutation point
  4360. rcall initialize_all_timings ; Initialize timing
  4361. rcall calc_new_wait_times ; Calculate new wait times
  4362. rjmp run1
  4363. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  4364. ;
  4365. ; Run entry point
  4366. ;
  4367. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  4368. damped_transition:
  4369. ; Transition from nondamped to damped if applicable
  4370. rcall decode_parameters ; Set programmed parameters
  4371. rcall comm6comm1
  4372. sts Adc_Conversion_Cnt, Zero ; Make sure a voltage reading is done next time
  4373. Set_Adc_Ip_Volt ; Set adc measurement to voltage
  4374. ; Run 1 = B(p-on) + C(n-pwm) - comparator A evaluated
  4375. ; Out_cA changes from low to high
  4376. run1:
  4377. Set_Comp_Phase_A XH ; Set comparator to phase A
  4378. rcall wait_for_comp_out_high ; Wait zero cross wait and wait for high
  4379. rcall evaluate_comparator_integrity ; Check whether comparator reading has been normal
  4380. rcall setup_comm_wait ; Setup wait time from zero cross to commutation
  4381. rcall calc_governor_target ; Calculate governor target
  4382. rcall wait_for_comm ; Wait from zero cross to commutation
  4383. rcall comm1comm2 ; Commutate
  4384. rcall calc_next_comm_timing ; Calculate next timing and start advance timing wait
  4385. rcall wait_advance_timing ; Wait advance timing and start zero cross wait
  4386. rcall calc_new_wait_times
  4387. rcall wait_before_zc_scan ; Wait zero cross wait and start zero cross timeout
  4388. ; Run 2 = A(p-on) + C(n-pwm) - comparator B evaluated
  4389. ; Out_cB changes from high to low
  4390. run2:
  4391. Set_Comp_Phase_B XH
  4392. rcall wait_for_comp_out_low
  4393. rcall evaluate_comparator_integrity
  4394. rcall setup_comm_wait
  4395. rcall calc_governor_prop_error
  4396. rcall wait_for_comm
  4397. rcall comm2comm3
  4398. rcall calc_next_comm_timing
  4399. rcall wait_advance_timing
  4400. rcall calc_new_wait_times
  4401. rcall wait_before_zc_scan
  4402. ; Run 3 = A(p-on) + B(n-pwm) - comparator C evaluated
  4403. ; Out_cC changes from low to high
  4404. run3:
  4405. Set_Comp_Phase_C XH
  4406. rcall wait_for_comp_out_high
  4407. rcall evaluate_comparator_integrity
  4408. rcall setup_comm_wait
  4409. rcall calc_governor_int_error
  4410. rcall wait_for_comm
  4411. rcall comm3comm4
  4412. rcall calc_next_comm_timing
  4413. rcall wait_advance_timing
  4414. rcall calc_new_wait_times
  4415. rcall wait_before_zc_scan
  4416. ; Run 4 = C(p-on) + B(n-pwm) - comparator A evaluated
  4417. ; Out_cA changes from high to low
  4418. run4:
  4419. Set_Comp_Phase_A XH
  4420. rcall wait_for_comp_out_low
  4421. rcall evaluate_comparator_integrity
  4422. rcall setup_comm_wait
  4423. rcall calc_governor_prop_correction
  4424. rcall wait_for_comm
  4425. rcall comm4comm5
  4426. rcall calc_next_comm_timing
  4427. rcall wait_advance_timing
  4428. rcall calc_new_wait_times
  4429. rcall wait_before_zc_scan
  4430. ; Run 5 = C(p-on) + A(n-pwm) - comparator B evaluated
  4431. ; Out_cB changes from low to high
  4432. run5:
  4433. Set_Comp_Phase_B XH
  4434. rcall wait_for_comp_out_high
  4435. rcall evaluate_comparator_integrity
  4436. rcall setup_comm_wait
  4437. rcall calc_governor_int_correction
  4438. rcall wait_for_comm
  4439. rcall comm5comm6
  4440. rcall calc_next_comm_timing
  4441. rcall wait_advance_timing
  4442. rcall calc_new_wait_times
  4443. rcall wait_before_zc_scan
  4444. ; Run 6 = B(p-on) + A(n-pwm) - comparator C evaluated
  4445. ; Out_cC changes from high to low
  4446. run6:
  4447. Set_Comp_Phase_C XH
  4448. rcall wait_for_comp_out_low
  4449. Start_Adc XH
  4450. rcall evaluate_comparator_integrity
  4451. rcall setup_comm_wait
  4452. rcall wait_for_comm
  4453. rcall comm6comm1
  4454. rcall calc_next_comm_timing
  4455. rcall wait_advance_timing
  4456. rcall calc_new_wait_times
  4457. rcall check_temp_voltage_and_limit_power
  4458. rcall wait_before_zc_scan
  4459. ; Check if it is startup
  4460. sbrs Flags1, STARTUP_PHASE
  4461. rjmp normal_run_checks
  4462. ; Set spoolup power variables
  4463. lds XH, Pwm_Spoolup_Beg
  4464. sts Pwm_Limit, XH ; Set initial max power
  4465. sts Pwm_Limit_Spoolup, XH ; Set initial slow spoolup power
  4466. lds XH, Auto_Bailout_Armed
  4467. sts Spoolup_Limit_Cnt, XH
  4468. ldi XH, 1
  4469. sts Spoolup_Limit_Skip, XH
  4470. ; Check startup ok counter
  4471. ldi Temp2, 100 ; Set nominal startup parameters
  4472. ldi Temp3, 20
  4473. .IF MODE >= 1 ; Tail or multi
  4474. lds XH, Pgm_Direction ; Check if bidirectional operation
  4475. cpi XH, 3
  4476. brne start_params_set ; No - branch
  4477. ldi Temp2, 30 ; Set faster startup parameters for bidirectional operation
  4478. ldi Temp3, 5
  4479. start_params_set:
  4480. .ENDIF
  4481. lds XH, Startup_Ok_Cnt ; Load ok counter
  4482. cp XH, Temp2 ; Is counter above requirement?
  4483. brcs start_check_rcp ; No - proceed
  4484. cbr Flags1, (1<<STARTUP_PHASE) ; Clear startup phase flag
  4485. sbr Flags1, (1<<INITIAL_RUN_PHASE) ; Set initial run phase flag
  4486. sts Startup_Rot_Cnt, Temp3 ; Set startup rotation count
  4487. .IF MODE == 1 ; Tail
  4488. ldi XH, 0xFF
  4489. sts Pwm_Limit, XH ; Allow full power
  4490. sts Pwm_Limit_Spoolup, XH
  4491. .ENDIF
  4492. .IF MODE == 2 ; Multi
  4493. lds Temp1, Pgm_Direction ; Check if bidirectional operation
  4494. cpi XH, 3
  4495. brne start_pwm_lim_set
  4496. ldi XH, 0xFF
  4497. sts Pwm_Limit, XH ; Allow full power in bidirectional operation
  4498. sts Pwm_Limit_Spoolup, XH
  4499. start_pwm_lim_set:
  4500. .ENDIF
  4501. rjmp normal_run_checks
  4502. start_check_rcp:
  4503. lds XH, New_Rcp ; Load new pulse value
  4504. cpi XH, RCP_STOP ; Check if pulse is below stop value
  4505. brcs PC+2
  4506. rjmp run1 ; Continue to run
  4507. rjmp run_to_wait_for_power_on
  4508. normal_run_checks:
  4509. ; Check if it is initial run phase
  4510. sbrs Flags1, INITIAL_RUN_PHASE ; If not initial run phase - branch
  4511. rjmp initial_run_phase_done
  4512. ; Decrement startup rotaton count
  4513. lds XH, Startup_Rot_Cnt
  4514. dec XH
  4515. ; Check number of nondamped rotations
  4516. brne normal_run_check_startup_rot ; Branch if counter is not zero
  4517. cbr Flags1, (1<<INITIAL_RUN_PHASE); Clear initial run phase flag
  4518. rjmp damped_transition ; Do damped transition if counter is zero
  4519. normal_run_check_startup_rot:
  4520. sts Startup_Rot_Cnt, XH ; Not zero - store counter
  4521. lds XH, New_Rcp ; Load new pulse value
  4522. cpi XH, RCP_STOP ; Check if pulse is below stop value
  4523. brcs PC+2
  4524. rjmp run1 ; Continue to run
  4525. rjmp run_to_wait_for_power_on
  4526. initial_run_phase_done:
  4527. .IF MODE == 0 ; Main
  4528. ; Check if throttle is zeroed
  4529. lds XH, Rcp_Stop_Cnt ; Load stop RC pulse counter value
  4530. cpi XH, 1 ; Is number of stop RC pulses above limit?
  4531. brcs run6_check_rcp_stop_count ; If no - branch
  4532. lds XH, Pwm_Spoolup_Beg ; If yes - set initial max powers
  4533. sts Pwm_Limit_Spoolup, XH
  4534. lds XH, Auto_Bailout_Armed ; And set spoolup parameters
  4535. sts Spoolup_Limit_Cnt, XH
  4536. ldi XH, 1
  4537. sts Spoolup_Limit_Skip, XH
  4538. run6_check_rcp_stop_count:
  4539. .ENDIF
  4540. ; Exit run loop after a given time
  4541. lds XH, Rcp_Stop_Cnt ; Load stop RC pulse counter value
  4542. cpi XH, RCP_STOP_LIMIT ; Is number of stop RC pulses above limit?
  4543. brcc run_to_wait_for_power_on ; Yes, go back to wait for poweron
  4544. run6_check_rcp_timeout:
  4545. mov XH, Flags3 ; Check pwm frequency flags
  4546. andi XH, ((1<<RCP_PWM_FREQ_1KHZ)+(1<<RCP_PWM_FREQ_2KHZ)+(1<<RCP_PWM_FREQ_4KHZ)+(1<<RCP_PWM_FREQ_8KHZ)+(1<<RCP_PWM_FREQ_12KHZ))
  4547. brne run6_check_speed ; If a flag is set (PWM) - branch
  4548. lds XH, Rcp_Timeout_Cnt ; Load RC pulse timeout counter value
  4549. tst XH
  4550. breq run_to_wait_for_power_on ; If it is zero - go back to wait for poweron
  4551. run6_check_speed:
  4552. lds XH, Comm_Period4x_H ; Is Comm_Period4x more than 32ms (~1220 eRPM)?
  4553. .IF CLK_8M == 0
  4554. cpi XH, 0xF0
  4555. .ELSE
  4556. cpi XH, 0x70
  4557. .ENDIF
  4558. brcc run_to_wait_for_power_on ; Yes - go back to motor start
  4559. rjmp run1 ; Go back to run 1
  4560. run_to_wait_for_power_on:
  4561. cli
  4562. rcall switch_power_off
  4563. lds Temp7, Pgm_Pwm_Freq ; Store setting in Temp7
  4564. ldi XH, 2 ; Set low pwm mode (in order to turn off damping)
  4565. sts Pgm_Pwm_Freq, XH
  4566. rcall decode_parameters ; (Decode_parameters uses Temp1 and Temp8)
  4567. sts Pgm_Pwm_Freq, Temp7 ; Restore settings
  4568. sts Requested_Pwm, Zero ; Set requested pwm to zero
  4569. sts Governor_Req_Pwm, Zero ; Set governor requested pwm to zero
  4570. sts Current_Pwm, Zero ; Set current pwm to zero
  4571. mov Current_Pwm_Limited, Zero ; Set limited current pwm to zero
  4572. sts Pwm_Motor_Idle, Zero ; Set motor idle to zero
  4573. cbr Flags1, (1<<MOTOR_SPINNING) ; Clear motor spinning flag
  4574. sei
  4575. rcall wait1ms ; Wait for pwm to be stopped
  4576. rcall switch_power_off
  4577. .IF MODE == 0 ; Main
  4578. mov XH, Flags3 ; Check pwm frequency flags
  4579. andi XH, ((1<<RCP_PWM_FREQ_1KHZ)+(1<<RCP_PWM_FREQ_2KHZ)+(1<<RCP_PWM_FREQ_4KHZ)+(1<<RCP_PWM_FREQ_8KHZ)+(1<<RCP_PWM_FREQ_12KHZ))
  4580. brne run_to_next_state_main ; If a flag is set (PWM) - branch
  4581. lds XH, Rcp_Timeout_Cnt ; Load RC pulse timeout counter value
  4582. tst XH
  4583. brne run_to_next_state_main ; If it is not zero - branch
  4584. rjmp measure_pwm_freq_init ; If it is zero (pulses missing) - go back to measure pwm frequency
  4585. run_to_next_state_main:
  4586. lds XH, Pgm_Main_Rearm_Start
  4587. cpi XH, 1 ; Is re-armed start enabled?
  4588. brcs jmp_wait_for_power_on ; No - do like tail and start immediately
  4589. rjmp validate_rcp_start ; Yes - go back to validate RC pulse
  4590. jmp_wait_for_power_on:
  4591. rjmp wait_for_power_on ; Go back to wait for power on
  4592. .ENDIF
  4593. .IF MODE >= 1 ; Tail or multi
  4594. mov XH, Flags3 ; Check pwm frequency flags
  4595. andi XH, ((1<<RCP_PWM_FREQ_1KHZ)+(1<<RCP_PWM_FREQ_2KHZ)+(1<<RCP_PWM_FREQ_4KHZ)+(1<<RCP_PWM_FREQ_8KHZ)+(1<<RCP_PWM_FREQ_12KHZ))
  4596. brne jmp_wait_for_power_on ; If a flag is set (PWM) - branch
  4597. lds XH, Rcp_Timeout_Cnt ; Load RC pulse timeout counter value
  4598. tst XH
  4599. brne jmp_wait_for_power_on ; If it is not zero - go back to wait for poweron
  4600. rjmp measure_pwm_freq_init ; If it is zero (pulses missing) - go back to measure pwm frequency
  4601. jmp_wait_for_power_on:
  4602. rjmp wait_for_power_on ; Go back to wait for power on
  4603. .ENDIF
  4604. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  4605. .INCLUDE "BLHeliTxPgm.inc" ; Include source code for programming the ESC with the TX
  4606. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  4607. .EXIT