You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
4554 lines
116 KiB
4554 lines
116 KiB
$NOMOD51
|
|
;**** **** **** **** ****
|
|
;
|
|
; BLHeli program for controlling brushless motors in multirotors
|
|
;
|
|
; Copyright 2011, 2012 Steffen Skaug
|
|
; This program is distributed under the terms of the GNU General Public License
|
|
;
|
|
; This file is part of BLHeli.
|
|
;
|
|
; BLHeli is free software: you can redistribute it and/or modify
|
|
; it under the terms of the GNU General Public License as published by
|
|
; the Free Software Foundation, either version 3 of the License, or
|
|
; (at your option) any later version.
|
|
;
|
|
; BLHeli is distributed in the hope that it will be useful,
|
|
; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
; GNU General Public License for more details.
|
|
;
|
|
; You should have received a copy of the GNU General Public License
|
|
; along with BLHeli. If not, see <http://www.gnu.org/licenses/>.
|
|
;
|
|
;**** **** **** **** ****
|
|
;
|
|
; This software was initially designed for use with Eflite mCP X, but is now adapted to copters/planes in general
|
|
;
|
|
; The software was inspired by and started from from Bernard Konze's BLMC: http://home.versanet.de/~bkonze/blc_6a/blc_6a.htm
|
|
; And also Simon Kirby's TGY: https://github.com/sim-/tgy
|
|
;
|
|
; This file is best viewed with tab width set to 5
|
|
;
|
|
; The code is designed for multirotor applications, running damped light mode
|
|
;
|
|
; The input signal can be Normal (1-2ms), OneShot125 (125-250us), OneShot42 (41.7-83.3us) or Multishot (5-25us) at rates as high as allowed by the format.
|
|
; Three Dshot signal rates are also supported, Dshot150, Dshot300 and Dshot600. A 48MHz MCU is required for Dshot600.
|
|
; The code autodetects normal, OneShot125, Oneshot42, Multishot or Dshot.
|
|
;
|
|
; The first lines of the software must be modified according to the chosen environment:
|
|
; ESCNO EQU "ESC"
|
|
; MCU_48MHZ EQU "N"
|
|
; FETON_DELAY EQU "N"
|
|
;
|
|
;**** **** **** **** ****
|
|
; Revision history:
|
|
; - Rev16.0 Started. Built upon rev 14.5 of base code
|
|
; Using hardware pwm for very smooth throttle response, silent running and support of very high rpms
|
|
; Implemented reverse bidirectional mode
|
|
; Implemented separate throttle gains fwd and rev in bidirectional mode
|
|
; Implemented support for Oneshot42 and Multishot
|
|
; - Rev16.1 Made low rpm power limiting programmable through the startup power parameter
|
|
; - Rev16.2 Fixed bug that prevented temperature protection
|
|
; Improved robustness to very high input signal rates
|
|
; Beeps can be turned off by programming beep strength to 1
|
|
; Throttle cal difference is checked to be above required minimum before storing. Throttle cal max is not stored until successful min throttle cal
|
|
; - Rev16.3 Implemented programmable temperature protection
|
|
; Improved protection of bootloader and generally reduced risk of flash corruption
|
|
; Some small changes for improved sync hold
|
|
; - Rev16.4 Fixed bug where bootloader operation could be blocked by a defective "eeprom" signature
|
|
; - Rev16.5 Added support for DShot150, DShot300 and DShot600
|
|
; - Rev16.6 Fixed signal detection issue of multishot at 32kHz
|
|
; Improved bidirectional mode for high input signal rates
|
|
; - Rev16.7 Addition of Dshot commands for beeps and temporary reverse direction (largely by brycedjohnson)
|
|
;
|
|
;
|
|
;**** **** **** **** ****
|
|
; Minimum 8K Bytes of In-System Self-Programmable Flash
|
|
; Minimum 512 Bytes Internal SRAM
|
|
;
|
|
;**** **** **** **** ****
|
|
; Master clock is internal 24MHz oscillator (or 48MHz, for which the times below are halved)
|
|
; Although 24/48 are used in the code, the exact clock frequencies are 24.5MHz or 49.0 MHz
|
|
; Timer 0 (41.67ns counts) always counts up and is used for
|
|
; - RC pulse measurement
|
|
; Timer 1 (41.67ns counts) always counts up and is used for
|
|
; - DShot frame sync detection
|
|
; Timer 2 (500ns counts) always counts up and is used for
|
|
; - RC pulse timeout counts and commutation times
|
|
; Timer 3 (500ns counts) always counts up and is used for
|
|
; - Commutation timeouts
|
|
; PCA0 (41.67ns counts) always counts up and is used for
|
|
; - Hardware PWM generation
|
|
;
|
|
;**** **** **** **** ****
|
|
; Interrupt handling
|
|
; The C8051 does not disable interrupts when entering an interrupt routine.
|
|
; Also some interrupt flags need to be cleared by software
|
|
; The code disables interrupts in some interrupt routines
|
|
; - Interrupts are disabled during beeps, to avoid audible interference from interrupts
|
|
;
|
|
;**** **** **** **** ****
|
|
; Motor control:
|
|
; - Brushless motor control with 6 states for each electrical 360 degrees
|
|
; - An advance timing of 0deg has zero cross 30deg after one commutation and 30deg before the next
|
|
; - Timing advance in this implementation is set to 15deg nominally
|
|
; - Motor pwm is always damped light (aka complementary pwm, regenerative braking)
|
|
; Motor sequence starting from zero crossing:
|
|
; - Timer wait: Wt_Comm 15deg ; Time to wait from zero cross to actual commutation
|
|
; - Timer wait: Wt_Advance 15deg ; Time to wait for timing advance. Nominal commutation point is after this
|
|
; - Timer wait: Wt_Zc_Scan 7.5deg ; Time to wait before looking for zero cross
|
|
; - Scan for zero cross 22.5deg ; Nominal, with some motor variations
|
|
;
|
|
; Motor startup:
|
|
; There is a startup phase and an initial run phase, before normal bemf commutation run begins.
|
|
;
|
|
;**** **** **** **** ****
|
|
; List of enumerated supported ESCs
|
|
A_ EQU 1 ; X X RC X MC MB MA CC X X Cc Cp Bc Bp Ac Ap
|
|
B_ EQU 2 ; X X RC X MC MB MA CC X X Ap Ac Bp Bc Cp Cc
|
|
C_ EQU 3 ; Ac Ap MC MB MA CC X RC X X X X Cc Cp Bc Bp
|
|
D_ EQU 4 ; X X RC X CC MA MC MB X X Cc Cp Bc Bp Ac Ap Com fets inverted
|
|
E_ EQU 5 ; L1 L0 RC X MC MB MA CC X L2 Cc Cp Bc Bp Ac Ap A with LEDs
|
|
F_ EQU 6 ; X X RC X MA MB MC CC X X Cc Cp Bc Bp Ac Ap
|
|
G_ EQU 7 ; X X RC X CC MA MC MB X X Cc Cp Bc Bp Ac Ap Like D, but noninverted com fets
|
|
H_ EQU 8 ; RC X X X MA MB CC MC X Ap Bp Cp X Ac Bc Cc
|
|
I_ EQU 9 ; X X RC X MC MB MA CC X X Ac Bc Cc Ap Bp Cp
|
|
J_ EQU 10 ; L2 L1 L0 RC CC MB MC MA X X Cc Bc Ac Cp Bp Ap LEDs
|
|
K_ EQU 11 ; X X MC X MB CC MA RC X X Ap Bp Cp Cc Bc Ac Com fets inverted
|
|
L_ EQU 12 ; X X RC X CC MA MB MC X X Ac Bc Cc Ap Bp Cp
|
|
M_ EQU 13 ; MA MC CC MB RC L0 X X X Cc Bc Ac Cp Bp Ap X LED
|
|
N_ EQU 14 ; X X RC X MC MB MA CC X X Cp Cc Bp Bc Ap Ac
|
|
O_ EQU 15 ; X X RC X CC MA MC MB X X Cc Cp Bc Bp Ac Ap Like D, but low side pwm
|
|
P_ EQU 16 ; X X RC MA CC MB MC X X Cc Bc Ac Cp Bp Ap X
|
|
Q_ EQU 17 ; Cp Bp Ap L1 L0 X RC X X MA MB MC CC Cc Bc Ac LEDs
|
|
R_ EQU 18 ; X X RC X MC MB MA CC X X Ac Bc Cc Ap Bp Cp
|
|
S_ EQU 19 ; X X RC X CC MA MC MB X X Cc Cp Bc Bp Ac Ap Like O, but com fets inverted
|
|
T_ EQU 20 ; RC X MA X MB CC MC X X X Cp Bp Ap Ac Bc Cc
|
|
U_ EQU 21 ; MA MC CC MB RC L0 L1 L2 X Cc Bc Ac Cp Bp Ap X Like M, but with 3 LEDs
|
|
V_ EQU 22 ; Cc X RC X MC CC MB MA X Ap Ac Bp X X Bc Cp
|
|
W_ EQU 23 ; RC MC MB X CC MA X X X Ap Bp Cp X X X X Tristate gate driver
|
|
X_ EQU 24 ; Reserved
|
|
Y_ EQU 25 ; Reserved
|
|
Z_ EQU 26 ; X X RC X CC MA MC MB X X Cp Cc Bp Bc Ap Ac Like S, but pwm fets inverted
|
|
|
|
;**** **** **** **** ****
|
|
; Select the port mapping to use (or unselect all for use with external batch compile file)
|
|
;ESCNO EQU A_
|
|
;ESCNO EQU B_
|
|
;ESCNO EQU C_
|
|
;ESCNO EQU D_
|
|
;ESCNO EQU E_
|
|
;ESCNO EQU F_
|
|
;ESCNO EQU G_
|
|
;ESCNO EQU H_
|
|
;ESCNO EQU I_
|
|
;ESCNO EQU J_
|
|
;ESCNO EQU K_
|
|
;ESCNO EQU L_
|
|
;ESCNO EQU M_
|
|
;ESCNO EQU N_
|
|
;ESCNO EQU O_
|
|
;ESCNO EQU P_
|
|
;ESCNO EQU Q_
|
|
;ESCNO EQU R_
|
|
;ESCNO EQU S_
|
|
;ESCNO EQU T_
|
|
;ESCNO EQU U_
|
|
;ESCNO EQU V_
|
|
;ESCNO EQU W_
|
|
;ESCNO EQU X_
|
|
;ESCNO EQU Y_
|
|
;ESCNO EQU Z_
|
|
|
|
;**** **** **** **** ****
|
|
; Select the MCU type (or unselect for use with external batch compile file)
|
|
;MCU_48MHZ EQU 1
|
|
|
|
;**** **** **** **** ****
|
|
; Select the fet deadtime (or unselect for use with external batch compile file)
|
|
;FETON_DELAY EQU 50 ; 20.4ns per step
|
|
|
|
|
|
;**** **** **** **** ****
|
|
; ESC selection statements
|
|
IF ESCNO == A_
|
|
$include (A.inc) ; Select pinout A
|
|
ENDIF
|
|
|
|
IF ESCNO == B_
|
|
$include (B.inc) ; Select pinout B
|
|
ENDIF
|
|
|
|
IF ESCNO == C_
|
|
$include (C.inc) ; Select pinout C
|
|
ENDIF
|
|
|
|
IF ESCNO == D_
|
|
$include (D.inc) ; Select pinout D
|
|
ENDIF
|
|
|
|
IF ESCNO == E_
|
|
$include (E.inc) ; Select pinout E
|
|
ENDIF
|
|
|
|
IF ESCNO == F_
|
|
$include (F.inc) ; Select pinout F
|
|
ENDIF
|
|
|
|
IF ESCNO == G_
|
|
$include (G.inc) ; Select pinout G
|
|
ENDIF
|
|
|
|
IF ESCNO == H_
|
|
$include (H.inc) ; Select pinout H
|
|
ENDIF
|
|
|
|
IF ESCNO == I_
|
|
$include (I.inc) ; Select pinout I
|
|
ENDIF
|
|
|
|
IF ESCNO == J_
|
|
$include (J.inc) ; Select pinout J
|
|
ENDIF
|
|
|
|
IF ESCNO == K_
|
|
$include (K.inc) ; Select pinout K
|
|
ENDIF
|
|
|
|
IF ESCNO == L_
|
|
$include (L.inc) ; Select pinout L
|
|
ENDIF
|
|
|
|
IF ESCNO == M_
|
|
$include (M.inc) ; Select pinout M
|
|
ENDIF
|
|
|
|
IF ESCNO == N_
|
|
$include (N.inc) ; Select pinout N
|
|
ENDIF
|
|
|
|
IF ESCNO == O_
|
|
$include (O.inc) ; Select pinout O
|
|
ENDIF
|
|
|
|
IF ESCNO == P_
|
|
$include (P.inc) ; Select pinout P
|
|
ENDIF
|
|
|
|
IF ESCNO == Q_
|
|
$include (Q.inc) ; Select pinout Q
|
|
ENDIF
|
|
|
|
IF ESCNO == R_
|
|
$include (R.inc) ; Select pinout R
|
|
ENDIF
|
|
|
|
IF ESCNO == S_
|
|
$include (S.inc) ; Select pinout S
|
|
ENDIF
|
|
|
|
IF ESCNO == T_
|
|
$include (T.inc) ; Select pinout T
|
|
ENDIF
|
|
|
|
IF ESCNO == U_
|
|
$include (U.inc) ; Select pinout U
|
|
ENDIF
|
|
|
|
IF ESCNO == V_
|
|
$include (V.inc) ; Select pinout V
|
|
ENDIF
|
|
|
|
IF ESCNO == W_
|
|
$include (W.inc) ; Select pinout W
|
|
ENDIF
|
|
|
|
IF ESCNO == X_
|
|
;$include (X.inc) ; Select pinout X
|
|
ENDIF
|
|
|
|
IF ESCNO == Y_
|
|
;$include (Y.inc) ; Select pinout Y
|
|
ENDIF
|
|
|
|
IF ESCNO == Z_
|
|
$include (Z.inc) ; Select pinout Z
|
|
ENDIF
|
|
|
|
|
|
;**** **** **** **** ****
|
|
; Programming defaults
|
|
;
|
|
DEFAULT_PGM_STARTUP_PWR EQU 9 ; 1=0.031 2=0.047 3=0.063 4=0.094 5=0.125 6=0.188 7=0.25 8=0.38 9=0.50 10=0.75 11=1.00 12=1.25 13=1.50
|
|
DEFAULT_PGM_COMM_TIMING EQU 3 ; 1=Low 2=MediumLow 3=Medium 4=MediumHigh 5=High
|
|
DEFAULT_PGM_DEMAG_COMP EQU 2 ; 1=Disabled 2=Low 3=High
|
|
DEFAULT_PGM_DIRECTION EQU 1 ; 1=Normal 2=Reversed 3=Bidir 4=Bidir rev
|
|
DEFAULT_PGM_BEEP_STRENGTH EQU 40 ; Beep strength
|
|
DEFAULT_PGM_BEACON_STRENGTH EQU 80 ; Beacon strength
|
|
DEFAULT_PGM_BEACON_DELAY EQU 4 ; 1=1m 2=2m 3=5m 4=10m 5=Infinite
|
|
|
|
; COMMON
|
|
DEFAULT_PGM_ENABLE_TX_PROGRAM EQU 1 ; 1=Enabled 0=Disabled
|
|
DEFAULT_PGM_MIN_THROTTLE EQU 37 ; 4*37+1000=1148
|
|
DEFAULT_PGM_MAX_THROTTLE EQU 208 ; 4*208+1000=1832
|
|
DEFAULT_PGM_CENTER_THROTTLE EQU 122 ; 4*122+1000=1488 (used in bidirectional mode)
|
|
DEFAULT_PGM_ENABLE_TEMP_PROT EQU 7 ; 0=Disabled 1=80C 2=90C 3=100C 4=110C 5=120C 6=130C 7=140C
|
|
DEFAULT_PGM_ENABLE_POWER_PROT EQU 1 ; 1=Enabled 0=Disabled
|
|
DEFAULT_PGM_BRAKE_ON_STOP EQU 0 ; 1=Enabled 0=Disabled
|
|
DEFAULT_PGM_LED_CONTROL EQU 0 ; Byte for LED control. 2bits per LED, 0=Off, 1=On
|
|
|
|
;**** **** **** **** ****
|
|
; Temporary register definitions
|
|
Temp1 EQU R0
|
|
Temp2 EQU R1
|
|
Temp3 EQU R2
|
|
Temp4 EQU R3
|
|
Temp5 EQU R4
|
|
Temp6 EQU R5
|
|
Temp7 EQU R6
|
|
Temp8 EQU R7
|
|
|
|
;**** **** **** **** ****
|
|
; Register definitions
|
|
DSEG AT 20h ; Variables segment
|
|
|
|
Bit_Access: DS 1 ; MUST BE AT THIS ADDRESS. Variable at bit accessible address (for non interrupt routines)
|
|
Bit_Access_Int: DS 1 ; Variable at bit accessible address (for interrupts)
|
|
|
|
Rcp_Outside_Range_Cnt: DS 1 ; RC pulse outside range counter (incrementing)
|
|
Rcp_Timeout_Cntd: DS 1 ; RC pulse timeout counter (decrementing)
|
|
|
|
|
|
Flags0: DS 1 ; State flags. Reset upon init_start
|
|
T3_PENDING EQU 0 ; Timer 3 pending flag
|
|
DEMAG_DETECTED EQU 1 ; Set when excessive demag time is detected
|
|
COMP_TIMED_OUT EQU 2 ; Set when comparator reading timed out
|
|
; EQU 3
|
|
; EQU 4
|
|
; EQU 5
|
|
; EQU 6
|
|
; EQU 7
|
|
|
|
|
|
Flags1: DS 1 ; State flags. Reset upon init_start
|
|
STARTUP_PHASE EQU 0 ; Set when in startup phase
|
|
INITIAL_RUN_PHASE EQU 1 ; Set when in initial run phase, before synchronized run is achieved
|
|
MOTOR_STARTED EQU 2 ; Set when motor is started
|
|
DIR_CHANGE_BRAKE EQU 3 ; Set when braking before direction change
|
|
HIGH_RPM EQU 4 ; Set when motor rpm is high (Comm_Period4x_H less than 2)
|
|
; EQU 5
|
|
; EQU 6
|
|
; EQU 7
|
|
|
|
Flags2: DS 1 ; State flags. NOT reset upon init_start
|
|
RCP_UPDATED EQU 0 ; New RC pulse length value available
|
|
RCP_ONESHOT125 EQU 1 ; RC pulse input is OneShot125 (125-250us)
|
|
RCP_ONESHOT42 EQU 2 ; RC pulse input is OneShot42 (41.67-83us)
|
|
RCP_MULTISHOT EQU 3 ; RC pulse input is Multishot (5-25us)
|
|
RCP_DSHOT EQU 4 ; RC pulse input is digital shot
|
|
RCP_DIR_REV EQU 5 ; RC pulse direction in bidirectional mode
|
|
RCP_FULL_RANGE EQU 6 ; When set full input signal range is used (1000-2000us) and stored calibration values are ignored
|
|
; EQU 7
|
|
|
|
Flags3: DS 1 ; State flags. NOT reset upon init_start
|
|
PGM_DIR_REV EQU 0 ; Programmed direction. 0=normal, 1=reversed
|
|
PGM_BIDIR_REV EQU 1 ; Programmed bidirectional direction. 0=normal, 1=reversed
|
|
PGM_BIDIR EQU 2 ; Programmed bidirectional operation. 0=normal, 1=bidirectional
|
|
; EQU 3
|
|
; EQU 4
|
|
; EQU 5
|
|
; EQU 6
|
|
; EQU 7
|
|
|
|
|
|
;**** **** **** **** ****
|
|
; RAM definitions
|
|
DSEG AT 30h ; Ram data segment, direct addressing
|
|
Initial_Arm: DS 1 ; Variable that is set during the first arm sequence after power on
|
|
|
|
Min_Throttle_L: DS 1 ; Minimum throttle scaled (lo byte)
|
|
Min_Throttle_H: DS 1 ; Minimum throttle scaled (hi byte)
|
|
Center_Throttle_L: DS 1 ; Center throttle scaled (lo byte)
|
|
Center_Throttle_H: DS 1 ; Center throttle scaled (hi byte)
|
|
Max_Throttle_L: DS 1 ; Maximum throttle scaled (lo byte)
|
|
Max_Throttle_H: DS 1 ; Maximum throttle scaled (hi byte)
|
|
|
|
Power_On_Wait_Cnt_L: DS 1 ; Power on wait counter (lo byte)
|
|
Power_On_Wait_Cnt_H: DS 1 ; Power on wait counter (hi byte)
|
|
|
|
Startup_Cnt: DS 1 ; Startup phase commutations counter (incrementing)
|
|
Startup_Zc_Timeout_Cntd: DS 1 ; Startup zero cross timeout counter (decrementing)
|
|
Initial_Run_Rot_Cntd: DS 1 ; Initial run rotations counter (decrementing)
|
|
Stall_Cnt: DS 1 ; Counts start/run attempts that resulted in stall. Reset upon a proper stop
|
|
Demag_Detected_Metric: DS 1 ; Metric used to gauge demag event frequency
|
|
Demag_Pwr_Off_Thresh: DS 1 ; Metric threshold above which power is cut
|
|
Low_Rpm_Pwr_Slope: DS 1 ; Sets the slope of power increase for low rpms
|
|
|
|
Timer0_X: DS 1 ; Timer 0 extended byte
|
|
Timer2_X: DS 1 ; Timer 2 extended byte
|
|
Prev_Comm_L: DS 1 ; Previous commutation timer 3 timestamp (lo byte)
|
|
Prev_Comm_H: DS 1 ; Previous commutation timer 3 timestamp (hi byte)
|
|
Prev_Comm_X: DS 1 ; Previous commutation timer 3 timestamp (ext byte)
|
|
Prev_Prev_Comm_L: DS 1 ; Pre-previous commutation timer 3 timestamp (lo byte)
|
|
Prev_Prev_Comm_H: DS 1 ; Pre-previous commutation timer 3 timestamp (hi byte)
|
|
Comm_Period4x_L: DS 1 ; Timer 3 counts between the last 4 commutations (lo byte)
|
|
Comm_Period4x_H: DS 1 ; Timer 3 counts between the last 4 commutations (hi byte)
|
|
Comparator_Read_Cnt: DS 1 ; Number of comparator reads done
|
|
|
|
Wt_Adv_Start_L: DS 1 ; Timer 3 start point for commutation advance timing (lo byte)
|
|
Wt_Adv_Start_H: DS 1 ; Timer 3 start point for commutation advance timing (hi byte)
|
|
Wt_Zc_Scan_Start_L: DS 1 ; Timer 3 start point from commutation to zero cross scan (lo byte)
|
|
Wt_Zc_Scan_Start_H: DS 1 ; Timer 3 start point from commutation to zero cross scan (hi byte)
|
|
Wt_Zc_Tout_Start_L: DS 1 ; Timer 3 start point for zero cross scan timeout (lo byte)
|
|
Wt_Zc_Tout_Start_H: DS 1 ; Timer 3 start point for zero cross scan timeout (hi byte)
|
|
Wt_Comm_Start_L: DS 1 ; Timer 3 start point from zero cross to commutation (lo byte)
|
|
Wt_Comm_Start_H: DS 1 ; Timer 3 start point from zero cross to commutation (hi byte)
|
|
|
|
Dshot_Cmd: DS 1 ; Dshot command
|
|
Dshot_Cmd_Cnt: DS 1 ; Dshot command count
|
|
|
|
New_Rcp: DS 1 ; New RC pulse value in pca counts
|
|
Rcp_Stop_Cnt: DS 1 ; Counter for RC pulses below stop value
|
|
|
|
Power_Pwm_Reg_L: DS 1 ; Power pwm register setting (lo byte)
|
|
Power_Pwm_Reg_H: DS 1 ; Power pwm register setting (hi byte). 0x3F is minimum power
|
|
Damp_Pwm_Reg_L: DS 1 ; Damping pwm register setting (lo byte)
|
|
Damp_Pwm_Reg_H: DS 1 ; Damping pwm register setting (hi byte)
|
|
Current_Power_Pwm_Reg_H: DS 1 ; Current power pwm register setting that is loaded in the PCA register (hi byte)
|
|
|
|
Pwm_Limit: DS 1 ; Maximum allowed pwm
|
|
Pwm_Limit_By_Rpm: DS 1 ; Maximum allowed pwm for low or high rpms
|
|
Pwm_Limit_Beg: DS 1 ; Initial pwm limit
|
|
|
|
Adc_Conversion_Cnt: DS 1 ; Adc conversion counter
|
|
|
|
Current_Average_Temp: DS 1 ; Current average temperature (lo byte ADC reading, assuming hi byte is 1)
|
|
|
|
Throttle_Gain: DS 1 ; Gain to be applied to RCP value
|
|
Throttle_Gain_M: DS 1 ; Gain to be applied to RCP value (multiplier 0=1x, 1=2x, 2=4x etc))
|
|
Throttle_Gain_BD_Rev: DS 1 ; Gain to be applied to RCP value for reverse direction in bidirectional mode
|
|
Throttle_Gain_BD_Rev_M: DS 1 ; Gain to be applied to RCP value for reverse direction in bidirectional mode (multiplier 0=1x, 1=2x, 2=4x etc)
|
|
Beep_Strength: DS 1 ; Strength of beeps
|
|
|
|
Skip_T2_Int: DS 1 ; Set for 48MHz MCUs when timer 2 interrupt shall be ignored
|
|
Clock_Set_At_48MHz: DS 1 ; Variable set if 48MHz MCUs run at 48MHz
|
|
|
|
Flash_Key_1: DS 1 ; Flash key one
|
|
Flash_Key_2: DS 1 ; Flash key two
|
|
|
|
Temp_Prot_Limit: DS 1 ; Temperature protection limit
|
|
|
|
DShot_Pwm_Thr: DS 1 ; DShot pulse width threshold value
|
|
DShot_Timer_Preset: DS 1 ; DShot timer preset for frame sync detection
|
|
DShot_Frame_Start_L: DS 1 ; DShot frame start timestamp (lo byte)
|
|
DShot_Frame_Start_H: DS 1 ; DShot frame start timestamp (hi byte)
|
|
DShot_Frame_Length_Thr: DS 1 ; DShot frame length criteria (in units of 4 timer 2 ticks)
|
|
|
|
; Indirect addressing data segment. The variables below must be in this sequence
|
|
ISEG AT 080h
|
|
_Pgm_Gov_P_Gain: DS 1 ; Programmed governor P gain
|
|
_Pgm_Gov_I_Gain: DS 1 ; Programmed governor I gain
|
|
_Pgm_Gov_Mode: DS 1 ; Programmed governor mode
|
|
_Pgm_Low_Voltage_Lim: DS 1 ; Programmed low voltage limit
|
|
_Pgm_Motor_Gain: DS 1 ; Programmed motor gain
|
|
_Pgm_Motor_Idle: DS 1 ; Programmed motor idle speed
|
|
Pgm_Startup_Pwr: DS 1 ; Programmed startup power
|
|
_Pgm_Pwm_Freq: DS 1 ; Programmed pwm frequency
|
|
Pgm_Direction: DS 1 ; Programmed rotation direction
|
|
Pgm_Input_Pol: DS 1 ; Programmed input pwm polarity
|
|
Initialized_L_Dummy: DS 1 ; Place holder
|
|
Initialized_H_Dummy: DS 1 ; Place holder
|
|
Pgm_Enable_TX_Program: DS 1 ; Programmed enable/disable value for TX programming
|
|
_Pgm_Main_Rearm_Start: DS 1 ; Programmed enable/disable re-arming main every start
|
|
_Pgm_Gov_Setup_Target: DS 1 ; Programmed main governor setup target
|
|
_Pgm_Startup_Rpm: DS 1 ; Programmed startup rpm (unused - place holder)
|
|
_Pgm_Startup_Accel: DS 1 ; Programmed startup acceleration (unused - place holder)
|
|
_Pgm_Volt_Comp: DS 1 ; Place holder
|
|
Pgm_Comm_Timing: DS 1 ; Programmed commutation timing
|
|
_Pgm_Damping_Force: DS 1 ; Programmed damping force (unused - place holder)
|
|
_Pgm_Gov_Range: DS 1 ; Programmed governor range
|
|
_Pgm_Startup_Method: DS 1 ; Programmed startup method (unused - place holder)
|
|
Pgm_Min_Throttle: DS 1 ; Programmed throttle minimum
|
|
Pgm_Max_Throttle: DS 1 ; Programmed throttle maximum
|
|
Pgm_Beep_Strength: DS 1 ; Programmed beep strength
|
|
Pgm_Beacon_Strength: DS 1 ; Programmed beacon strength
|
|
Pgm_Beacon_Delay: DS 1 ; Programmed beacon delay
|
|
_Pgm_Throttle_Rate: DS 1 ; Programmed throttle rate (unused - place holder)
|
|
Pgm_Demag_Comp: DS 1 ; Programmed demag compensation
|
|
_Pgm_BEC_Voltage_High: DS 1 ; Programmed BEC voltage
|
|
Pgm_Center_Throttle: DS 1 ; Programmed throttle center (in bidirectional mode)
|
|
_Pgm_Main_Spoolup_Time: DS 1 ; Programmed main spoolup time
|
|
Pgm_Enable_Temp_Prot: DS 1 ; Programmed temperature protection enable
|
|
Pgm_Enable_Power_Prot: DS 1 ; Programmed low rpm power protection enable
|
|
_Pgm_Enable_Pwm_Input: DS 1 ; Programmed PWM input signal enable
|
|
_Pgm_Pwm_Dither: DS 1 ; Programmed output PWM dither
|
|
Pgm_Brake_On_Stop: DS 1 ; Programmed braking when throttle is zero
|
|
Pgm_LED_Control: DS 1 ; Programmed LED control
|
|
|
|
; The sequence of the variables below is no longer of importance
|
|
Pgm_Startup_Pwr_Decoded: DS 1 ; Programmed startup power decoded
|
|
|
|
|
|
; Indirect addressing data segment
|
|
ISEG AT 0D0h
|
|
Temp_Storage: DS 48 ; Temporary storage
|
|
|
|
;**** **** **** **** ****
|
|
CSEG AT 1A00h ; "Eeprom" segment
|
|
EEPROM_FW_MAIN_REVISION EQU 16 ; Main revision of the firmware
|
|
EEPROM_FW_SUB_REVISION EQU 7 ; Sub revision of the firmware
|
|
EEPROM_LAYOUT_REVISION EQU 33 ; Revision of the EEPROM layout
|
|
|
|
Eep_FW_Main_Revision: DB EEPROM_FW_MAIN_REVISION ; EEPROM firmware main revision number
|
|
Eep_FW_Sub_Revision: DB EEPROM_FW_SUB_REVISION ; EEPROM firmware sub revision number
|
|
Eep_Layout_Revision: DB EEPROM_LAYOUT_REVISION ; EEPROM layout revision number
|
|
|
|
_Eep_Pgm_Gov_P_Gain: DB 0FFh
|
|
_Eep_Pgm_Gov_I_Gain: DB 0FFh
|
|
_Eep_Pgm_Gov_Mode: DB 0FFh
|
|
_Eep_Pgm_Low_Voltage_Lim: DB 0FFh
|
|
_Eep_Pgm_Motor_Gain: DB 0FFh
|
|
_Eep_Pgm_Motor_Idle: DB 0FFh
|
|
Eep_Pgm_Startup_Pwr: DB DEFAULT_PGM_STARTUP_PWR ; EEPROM copy of programmed startup power
|
|
_Eep_Pgm_Pwm_Freq: DB 0FFh
|
|
Eep_Pgm_Direction: DB DEFAULT_PGM_DIRECTION ; EEPROM copy of programmed rotation direction
|
|
_Eep_Pgm_Input_Pol: DB 0FFh
|
|
Eep_Initialized_L: DB 055h ; EEPROM initialized signature low byte
|
|
Eep_Initialized_H: DB 0AAh ; EEPROM initialized signature high byte
|
|
Eep_Enable_TX_Program: DB DEFAULT_PGM_ENABLE_TX_PROGRAM ; EEPROM TX programming enable
|
|
_Eep_Main_Rearm_Start: DB 0FFh
|
|
_Eep_Pgm_Gov_Setup_Target: DB 0FFh
|
|
_Eep_Pgm_Startup_Rpm: DB 0FFh
|
|
_Eep_Pgm_Startup_Accel: DB 0FFh
|
|
_Eep_Pgm_Volt_Comp: DB 0FFh
|
|
Eep_Pgm_Comm_Timing: DB DEFAULT_PGM_COMM_TIMING ; EEPROM copy of programmed commutation timing
|
|
_Eep_Pgm_Damping_Force: DB 0FFh
|
|
_Eep_Pgm_Gov_Range: DB 0FFh
|
|
_Eep_Pgm_Startup_Method: DB 0FFh
|
|
Eep_Pgm_Min_Throttle: DB DEFAULT_PGM_MIN_THROTTLE ; EEPROM copy of programmed minimum throttle
|
|
Eep_Pgm_Max_Throttle: DB DEFAULT_PGM_MAX_THROTTLE ; EEPROM copy of programmed minimum throttle
|
|
Eep_Pgm_Beep_Strength: DB DEFAULT_PGM_BEEP_STRENGTH ; EEPROM copy of programmed beep strength
|
|
Eep_Pgm_Beacon_Strength: DB DEFAULT_PGM_BEACON_STRENGTH ; EEPROM copy of programmed beacon strength
|
|
Eep_Pgm_Beacon_Delay: DB DEFAULT_PGM_BEACON_DELAY ; EEPROM copy of programmed beacon delay
|
|
_Eep_Pgm_Throttle_Rate: DB 0FFh
|
|
Eep_Pgm_Demag_Comp: DB DEFAULT_PGM_DEMAG_COMP ; EEPROM copy of programmed demag compensation
|
|
_Eep_Pgm_BEC_Voltage_High: DB 0FFh
|
|
Eep_Pgm_Center_Throttle: DB DEFAULT_PGM_CENTER_THROTTLE ; EEPROM copy of programmed center throttle
|
|
_Eep_Pgm_Main_Spoolup_Time: DB 0FFh
|
|
Eep_Pgm_Temp_Prot_Enable: DB DEFAULT_PGM_ENABLE_TEMP_PROT ; EEPROM copy of programmed temperature protection enable
|
|
Eep_Pgm_Enable_Power_Prot: DB DEFAULT_PGM_ENABLE_POWER_PROT ; EEPROM copy of programmed low rpm power protection enable
|
|
_Eep_Pgm_Enable_Pwm_Input: DB 0FFh
|
|
_Eep_Pgm_Pwm_Dither: DB 0FFh
|
|
Eep_Pgm_Brake_On_Stop: DB DEFAULT_PGM_BRAKE_ON_STOP ; EEPROM copy of programmed braking when throttle is zero
|
|
Eep_Pgm_LED_Control: DB DEFAULT_PGM_LED_CONTROL ; EEPROM copy of programmed LED control
|
|
|
|
Eep_Dummy: DB 0FFh ; EEPROM address for safety reason
|
|
|
|
CSEG AT 1A60h
|
|
Eep_Name: DB " " ; Name tag (16 Bytes)
|
|
|
|
;**** **** **** **** ****
|
|
Interrupt_Table_Definition ; SiLabs interrupts
|
|
CSEG AT 80h ; Code segment after interrupt vectors
|
|
|
|
;**** **** **** **** ****
|
|
|
|
; Table definitions
|
|
STARTUP_POWER_TABLE: DB 04h, 06h, 08h, 0Ch, 10h, 18h, 20h, 30h, 40h, 60h, 80h, 0A0h, 0C0h
|
|
|
|
|
|
;**** **** **** **** **** **** **** **** **** **** **** **** ****
|
|
;
|
|
; Timer 0 interrupt routine
|
|
;
|
|
; No assumptions
|
|
;
|
|
;**** **** **** **** **** **** **** **** **** **** **** **** ****
|
|
IF MCU_48MHZ == 1
|
|
t0_int:
|
|
inc Timer0_X
|
|
reti
|
|
ENDIF
|
|
|
|
|
|
;**** **** **** **** **** **** **** **** **** **** **** **** ****
|
|
;
|
|
; Timer 1 interrupt routine
|
|
;
|
|
; No assumptions
|
|
;
|
|
;**** **** **** **** **** **** **** **** **** **** **** **** ****
|
|
t1_int:
|
|
clr IE_EA
|
|
clr IE_EX0 ; Disable int0 interrupts
|
|
anl EIE1, #0EFh ; Disable pca interrupts
|
|
clr TCON_TR1 ; Stop timer 1
|
|
mov TL1, DShot_Timer_Preset ; Reset sync timer
|
|
push PSW
|
|
setb PSW.3 ; Select register bank 1 for this interrupt
|
|
push ACC
|
|
push B ; Will be pop'ed by int0 exit
|
|
clr TMR2CN0_TR2 ; Timer 2 disabled
|
|
mov Temp1, TMR2L ; Read timer value
|
|
mov Temp2, TMR2H
|
|
setb TMR2CN0_TR2 ; Timer 2 enabled
|
|
setb IE_EA
|
|
; Reset timer 0
|
|
mov TL0, #0
|
|
; Check frame time length
|
|
clr C
|
|
mov A, Temp1
|
|
subb A, DShot_Frame_Start_L
|
|
mov Temp1, A
|
|
mov A, Temp2
|
|
subb A, DShot_Frame_Start_H
|
|
mov Temp2, A
|
|
; Divide by 2 (or 4 for 48MHz). Unit is then us
|
|
clr C
|
|
mov A, Temp2
|
|
rrc A
|
|
mov Temp2, A
|
|
mov A, Temp1
|
|
rrc A
|
|
mov Temp1, A
|
|
mov A, Clock_Set_At_48MHz
|
|
jz t1_int_frame_time_scaled
|
|
|
|
clr C
|
|
mov A, Temp2
|
|
rrc A
|
|
mov Temp2, A
|
|
mov A, Temp1
|
|
rrc A
|
|
mov Temp1, A
|
|
|
|
t1_int_frame_time_scaled:
|
|
mov A, Temp2
|
|
jnz t1_int_msb_fail ; Frame too long
|
|
mov A, Temp1
|
|
subb A, DShot_Frame_Length_Thr
|
|
jc t1_int_msb_fail ; Frame too short
|
|
subb A, DShot_Frame_Length_Thr
|
|
jnc t1_int_msb_fail ; Frame too long
|
|
|
|
; Check that correct number of pulses is received
|
|
mov A, DPL ; Read current pointer
|
|
cjne A, #16, t1_int_msb_fail
|
|
|
|
; Decode transmitted data
|
|
mov Temp5, #0 ; Reset timestamp
|
|
mov Temp4, #0 ; High byte of receive buffer
|
|
mov Temp3, #0 ; Low byte of receive buffer
|
|
mov Temp2, #8 ; Number of bits per byte
|
|
mov DPTR, #0 ; Set pointer
|
|
mov Temp1, DShot_Pwm_Thr; DShot pulse width criteria
|
|
mov A, Clock_Set_At_48MHz
|
|
jnz t1_int_decode
|
|
|
|
clr C
|
|
mov A, Temp1 ; Scale pulse width criteria
|
|
rrc A
|
|
mov Temp1, A
|
|
|
|
t1_int_decode:
|
|
ajmp t1_int_decode_msb
|
|
|
|
t1_int_msb_fail:
|
|
mov DPTR, #0 ; Set pointer to start
|
|
setb IE_EX0 ; Enable int0 interrupts
|
|
setb IE_EX1 ; Enable int1 interrupts
|
|
ajmp int0_int_outside_range
|
|
|
|
t1_int_decode_msb:
|
|
; Decode DShot data Msb. Use more code space to save time (by not using loop)
|
|
Decode_DShot_2Msb
|
|
Decode_DShot_2Msb
|
|
Decode_DShot_2Msb
|
|
Decode_DShot_2Msb
|
|
ajmp t1_int_decode_lsb
|
|
|
|
t1_int_lsb_fail:
|
|
mov DPTR, #0 ; Set pointer to start
|
|
setb IE_EX0 ; Enable int0 interrupts
|
|
setb IE_EX1 ; Enable int1 interrupts
|
|
ajmp int0_int_outside_range
|
|
|
|
t1_int_decode_lsb:
|
|
; Decode DShot data Lsb
|
|
Decode_DShot_2Lsb
|
|
Decode_DShot_2Lsb
|
|
Decode_DShot_2Lsb
|
|
Decode_DShot_2Lsb
|
|
; XOR check (in inverted data, which is ok)
|
|
mov A, Temp4
|
|
swap A
|
|
xrl A, Temp4
|
|
xrl A, Temp3
|
|
anl A, #0F0h
|
|
mov Temp2, A
|
|
mov A, Temp3
|
|
swap A
|
|
anl A, #0F0h
|
|
clr C
|
|
subb A, Temp2
|
|
jz t1_int_xor_ok ; XOR check
|
|
|
|
mov DPTR, #0 ; Set pointer to start
|
|
setb IE_EX0 ; Enable int0 interrupts
|
|
setb IE_EX1 ; Enable int1 interrupts
|
|
ajmp int0_int_outside_range
|
|
|
|
t1_int_xor_ok:
|
|
; Swap to be LSB aligned to 12 bits (and invert)
|
|
mov A, Temp4
|
|
cpl A
|
|
swap A
|
|
anl A, #0F0h ; Low nibble of high byte
|
|
mov Temp2, A
|
|
mov A, Temp3
|
|
cpl A
|
|
swap A
|
|
anl A, #0Fh ; High nibble of low byte
|
|
orl A, Temp2
|
|
mov Temp3, A
|
|
mov A, Temp4 ; High nibble of high byte
|
|
cpl A
|
|
swap A
|
|
anl A, #0Fh
|
|
mov Temp4, A
|
|
; Subtract 96 (still 12 bits)
|
|
clr C
|
|
mov A, Temp3
|
|
mov Temp2, A
|
|
subb A, #96
|
|
mov Temp3, A
|
|
mov A, Temp4
|
|
subb A, #0
|
|
mov Temp4, A
|
|
jnc t1_normal_range
|
|
|
|
clr C
|
|
mov A, Temp2 ; Check for 0 or dshot command
|
|
mov Temp4, #0
|
|
mov Temp3, #0
|
|
mov Temp2, #0
|
|
jz t1_normal_range
|
|
|
|
clr C ; We are in the special dshot range
|
|
rrc A ; Divide by 2
|
|
jnc t1_dshot_set_cmd ; Check for tlm bit set (if not telemetry, Temp2 will be zero and result in invalid command)
|
|
|
|
mov Temp2, A
|
|
clr C
|
|
subb A, Dshot_Cmd
|
|
jz t1_dshot_inc_cmd_cnt
|
|
|
|
t1_dshot_set_cmd:
|
|
mov A, Temp2
|
|
mov Dshot_Cmd, A
|
|
mov Dshot_Cmd_Cnt, #0
|
|
mov Temp2, #0
|
|
jmp t1_normal_range
|
|
|
|
t1_dshot_inc_cmd_cnt:
|
|
inc Dshot_Cmd_Cnt
|
|
|
|
t1_normal_range:
|
|
; Check for bidirectional operation (0=stop, 96-2095->fwd, 2096-4095->rev)
|
|
jnb Flags3.PGM_BIDIR, t1_int_not_bidir ; If not bidirectional operation - branch
|
|
|
|
; Subtract 2000 (still 12 bits)
|
|
clr C
|
|
mov A, Temp3
|
|
subb A, #0D0h
|
|
mov Temp1, A
|
|
mov A, Temp4
|
|
subb A, #07h
|
|
mov Temp2, A
|
|
jc t1_int_bidir_fwd ; If result is negative - branch
|
|
|
|
mov A, Temp1
|
|
mov Temp3, A
|
|
mov A, Temp2
|
|
mov Temp4, A
|
|
jb Flags2.RCP_DIR_REV, t1_int_bidir_rev_chk ; If same direction - branch
|
|
|
|
setb Flags2.RCP_DIR_REV
|
|
ajmp t1_int_bidir_rev_chk
|
|
|
|
t1_int_bidir_fwd:
|
|
jnb Flags2.RCP_DIR_REV, t1_int_bidir_rev_chk ; If same direction - branch
|
|
|
|
clr Flags2.RCP_DIR_REV
|
|
|
|
t1_int_bidir_rev_chk:
|
|
jb Flags3.PGM_BIDIR_REV, ($+5)
|
|
|
|
cpl Flags2.RCP_DIR_REV
|
|
|
|
clr C ; Multiply throttle value by 2
|
|
mov A, Temp3
|
|
rlc A
|
|
mov Temp3, A
|
|
mov A, Temp4
|
|
rlc A
|
|
mov Temp4, A
|
|
t1_int_not_bidir:
|
|
; Generate 4/256
|
|
mov A, Temp4
|
|
add A, Temp4
|
|
addc A, Temp4
|
|
addc A, Temp4
|
|
mov Temp2, A
|
|
; Align to 11 bits
|
|
clr C
|
|
mov A, Temp4
|
|
rrc A
|
|
mov Temp4, A
|
|
mov A, Temp3
|
|
rrc A
|
|
mov Temp3, A
|
|
; Scale from 2000 to 2048
|
|
mov A, Temp3
|
|
add A, Temp2 ; Holds 4/128
|
|
mov Temp3, A
|
|
mov A, Temp4
|
|
addc A, #0
|
|
mov Temp4, A
|
|
jnb ACC.3, ($+7)
|
|
|
|
mov Temp3, #0FFh
|
|
mov Temp4, #0FFh
|
|
|
|
; Boost pwm during direct start
|
|
mov A, Flags1
|
|
anl A, #((1 SHL STARTUP_PHASE)+(1 SHL INITIAL_RUN_PHASE))
|
|
jz t1_int_startup_boosted
|
|
|
|
jb Flags1.MOTOR_STARTED, t1_int_startup_boosted ; Do not boost when changing direction in bidirectional mode
|
|
|
|
mov A, Pwm_Limit_Beg ; Set 25% of max startup power as minimum power
|
|
rlc A
|
|
mov Temp2, A
|
|
mov A, Temp4
|
|
jnz t1_int_startup_boost_stall
|
|
|
|
clr C
|
|
mov A, Temp2
|
|
subb A, Temp3
|
|
jc t1_int_startup_boost_stall
|
|
|
|
mov A, Temp2
|
|
mov Temp3, A
|
|
|
|
t1_int_startup_boost_stall:
|
|
mov A, Stall_Cnt ; Add an extra power boost during start
|
|
swap A
|
|
rlc A
|
|
add A, Temp3
|
|
mov Temp3, A
|
|
mov A, Temp4
|
|
addc A, #0
|
|
mov Temp4, A
|
|
|
|
t1_int_startup_boosted:
|
|
; Set 8bit value
|
|
clr C
|
|
mov A, Temp3
|
|
rlc A
|
|
swap A
|
|
anl A, #0Fh
|
|
mov Temp1, A
|
|
mov A, Temp4
|
|
rlc A
|
|
swap A
|
|
anl A, #0F0h
|
|
orl A, Temp1
|
|
mov Temp1, A
|
|
jnz t1_int_zero_rcp_checked ; New_Rcp (Temp1) is only zero if all 11 bits are zero
|
|
|
|
mov A, Temp3
|
|
jz t1_int_zero_rcp_checked
|
|
|
|
mov Temp1, #1
|
|
|
|
t1_int_zero_rcp_checked:
|
|
; Align to 10 bits for 24MHz MCU
|
|
IF MCU_48MHZ == 0
|
|
clr C
|
|
mov A, Temp4
|
|
rrc A
|
|
mov Temp4, A
|
|
mov A, Temp3
|
|
rrc A
|
|
mov Temp3, A
|
|
ENDIF
|
|
mov DPTR, #0 ; Set pointer to start
|
|
setb IE_EX0 ; Enable int0 interrupts
|
|
setb IE_EX1 ; Enable int1 interrupts
|
|
; Decrement outside range counter
|
|
mov A, Rcp_Outside_Range_Cnt
|
|
jz ($+4)
|
|
|
|
dec Rcp_Outside_Range_Cnt
|
|
|
|
ajmp int0_int_pulse_ready
|
|
|
|
t1_int_frame_fail:
|
|
mov DPTR, #0 ; Set pointer to start
|
|
setb IE_EX0 ; Enable int0 interrupts
|
|
setb IE_EX1 ; Enable int1 interrupts
|
|
ajmp int0_int_outside_range
|
|
|
|
|
|
;**** **** **** **** **** **** **** **** **** **** **** **** ****
|
|
;
|
|
; Timer 2 interrupt routine
|
|
;
|
|
; No assumptions
|
|
; Requirements: Temp variables can NOT be used since PSW.x is not set
|
|
;
|
|
;**** **** **** **** **** **** **** **** **** **** **** **** ****
|
|
t2_int: ; Happens every 32ms
|
|
push PSW ; Preserve registers through interrupt
|
|
push ACC
|
|
clr TMR2CN0_TF2H ; Clear interrupt flag
|
|
inc Timer2_X
|
|
IF MCU_48MHZ == 1
|
|
mov A, Clock_Set_At_48MHz
|
|
jz t2_int_start
|
|
|
|
; Check skip variable
|
|
mov A, Skip_T2_Int
|
|
jz t2_int_start ; Execute this interrupt
|
|
|
|
mov Skip_T2_Int, #0
|
|
ajmp t2_int_exit
|
|
|
|
t2_int_start:
|
|
mov Skip_T2_Int, #1 ; Skip next interrupt
|
|
ENDIF
|
|
; Update RC pulse timeout counter
|
|
mov A, Rcp_Timeout_Cntd ; RC pulse timeout count zero?
|
|
jz ($+4) ; Yes - do not decrement
|
|
|
|
dec Rcp_Timeout_Cntd ; No decrement
|
|
|
|
; Check RC pulse against stop value
|
|
clr C
|
|
mov A, New_Rcp ; Load new pulse value
|
|
jz t2_int_rcp_stop ; Check if pulse is below stop value
|
|
|
|
; RC pulse higher than stop value, reset stop counter
|
|
mov Rcp_Stop_Cnt, #0 ; Reset rcp stop counter
|
|
ajmp t2_int_exit
|
|
|
|
t2_int_rcp_stop:
|
|
; RC pulse less than stop value
|
|
mov A, Rcp_Stop_Cnt ; Increment stop counter
|
|
add A, #1
|
|
mov Rcp_Stop_Cnt, A
|
|
jnc ($+5) ; Branch if counter has not wrapped
|
|
|
|
mov Rcp_Stop_Cnt, #0FFh ; Set stop counter to max
|
|
|
|
t2_int_exit:
|
|
pop ACC ; Restore preserved registers
|
|
pop PSW
|
|
reti
|
|
|
|
|
|
;**** **** **** **** **** **** **** **** **** **** **** **** ****
|
|
;
|
|
; Timer 3 interrupt routine
|
|
;
|
|
; No assumptions
|
|
; Requirements: Temp variables can NOT be used since PSW.x is not set
|
|
; ACC can not be used, as it is not pushed to stack
|
|
;
|
|
;**** **** **** **** **** **** **** **** **** **** **** **** ****
|
|
t3_int: ; Used for commutation timing
|
|
clr IE_EA ; Disable all interrupts
|
|
anl EIE1, #7Fh ; Disable timer 3 interrupts
|
|
mov TMR3RLL, #0FAh ; Set a short delay before next interrupt
|
|
mov TMR3RLH, #0FFh
|
|
clr Flags0.T3_PENDING ; Flag that timer has wrapped
|
|
anl TMR3CN0, #07Fh ; Timer 3 interrupt flag cleared
|
|
setb IE_EA ; Enable all interrupts
|
|
reti
|
|
|
|
|
|
;**** **** **** **** **** **** **** **** **** **** **** **** ****
|
|
;
|
|
; Int0 interrupt routine
|
|
;
|
|
; No assumptions
|
|
;
|
|
;**** **** **** **** **** **** **** **** **** **** **** **** ****
|
|
int0_int: ; Used for RC pulse timing
|
|
push ACC
|
|
mov A, TL0 ; Read pwm for DShot immediately
|
|
; Test for DShot
|
|
jnb Flags2.RCP_DSHOT, int0_int_not_dshot
|
|
|
|
mov TL1, DShot_Timer_Preset ; Reset sync timer
|
|
movx @DPTR, A ; Store pwm
|
|
inc DPTR
|
|
pop ACC
|
|
reti
|
|
|
|
; Not DShot
|
|
int0_int_not_dshot:
|
|
pop ACC
|
|
clr IE_EA
|
|
anl EIE1, #0EFh ; Disable pca interrupts
|
|
push PSW ; Preserve registers through interrupt
|
|
push ACC
|
|
push B
|
|
setb PSW.3 ; Select register bank 1 for this interrupt
|
|
setb IE_EA
|
|
; Get the counter values
|
|
Get_Rcp_Capture_Values
|
|
; Scale down to 10 bits (for 24MHz, and 11 bits for 48MHz)
|
|
jnb Flags2.RCP_MULTISHOT, int0_int_fall_not_multishot
|
|
|
|
; Multishot - Multiply by 2 and add 1/16 and 1/32
|
|
mov A, Temp1 ; Divide by 16
|
|
swap A
|
|
anl A, #0Fh
|
|
mov Temp3, A
|
|
mov A, Temp2
|
|
swap A
|
|
anl A, #0F0h
|
|
orl A, Temp3
|
|
mov Temp3, A
|
|
clr C ; Make divided by 32
|
|
rrc A
|
|
add A, Temp3 ; Add 1/16 to 1/32
|
|
mov Temp3, A
|
|
clr C ; Multiply by 2
|
|
mov A, Temp1
|
|
rlc A
|
|
mov Temp1, A
|
|
mov A, Temp2
|
|
rlc A
|
|
mov Temp2, A
|
|
mov A, Temp1 ; Add 1/16 and 1/32
|
|
add A, Temp3
|
|
mov Temp3, A
|
|
mov A, Temp2
|
|
IF MCU_48MHZ == 0
|
|
addc A, #03h ; Add to low end, to make signal look like 20-40us
|
|
ELSE
|
|
addc A, #06h
|
|
ENDIF
|
|
mov Temp4, A
|
|
ajmp int0_int_fall_gain_done
|
|
|
|
int0_int_fall_not_multishot:
|
|
jnb Flags2.RCP_ONESHOT42, int0_int_fall_not_oneshot_42
|
|
|
|
; Oneshot42 - Add 2/256
|
|
clr C
|
|
mov A, Temp1
|
|
rlc A
|
|
mov A, Temp2
|
|
rlc A
|
|
mov Temp3, A
|
|
mov A, Temp1
|
|
add A, Temp3
|
|
mov Temp3, A
|
|
mov A, Temp2
|
|
addc A, #0
|
|
mov Temp4, A
|
|
ajmp int0_int_fall_gain_done
|
|
|
|
int0_int_fall_not_oneshot_42:
|
|
jnb Flags2.RCP_ONESHOT125, int0_int_fall_not_oneshot_125
|
|
|
|
; Oneshot125 - multiply by 86/256
|
|
mov A, Temp1 ; Multiply by 86 and divide by 256
|
|
mov B, #56h
|
|
mul AB
|
|
mov Temp3, B
|
|
mov A, Temp2
|
|
mov B, #56h
|
|
mul AB
|
|
add A, Temp3
|
|
mov Temp3, A
|
|
xch A, B
|
|
addc A, #0
|
|
mov Temp4, A
|
|
ajmp int0_int_fall_gain_done
|
|
|
|
int0_int_fall_not_oneshot_125:
|
|
; Regular signal - multiply by 43/1024
|
|
IF MCU_48MHZ == 1
|
|
clr C
|
|
mov A, Temp3 ; Divide by 2
|
|
rrc A
|
|
mov Temp3, A
|
|
mov A, Temp2
|
|
rrc A
|
|
mov Temp2, A
|
|
mov A, Temp1
|
|
rrc A
|
|
mov Temp1, A
|
|
ENDIF
|
|
mov A, Temp1 ; Multiply by 43 and divide by 1024
|
|
IF MCU_48MHZ == 0
|
|
mov B, #2Bh
|
|
ELSE
|
|
mov B, #56h ; Multiply by 86
|
|
ENDIF
|
|
mul AB
|
|
mov Temp3, B
|
|
mov A, Temp2
|
|
IF MCU_48MHZ == 0
|
|
mov B, #2Bh
|
|
ELSE
|
|
mov B, #56h ; Multiply by 86
|
|
ENDIF
|
|
mul AB
|
|
add A, Temp3
|
|
mov Temp3, A
|
|
xch A, B
|
|
addc A, #0
|
|
clr C
|
|
rrc A ; Divide by 2 for total 512
|
|
mov Temp4, A
|
|
mov A, Temp3
|
|
rrc A
|
|
mov Temp3, A
|
|
clr C
|
|
mov A, Temp4 ; Divide by 2 for total 1024
|
|
rrc A
|
|
mov Temp4, A
|
|
mov A, Temp3
|
|
rrc A
|
|
mov Temp3, A
|
|
|
|
int0_int_fall_gain_done:
|
|
; Check if 2235us or above (in order to ignore false pulses)
|
|
clr C
|
|
mov A, Temp4 ; Is pulse 2235us or higher?
|
|
IF MCU_48MHZ == 0
|
|
subb A, #09h
|
|
ELSE
|
|
subb A, #12h
|
|
ENDIF
|
|
jnc int0_int_outside_range ; Yes - ignore pulse
|
|
|
|
; Check if below 900us (in order to ignore false pulses)
|
|
clr C
|
|
mov A, Temp3
|
|
IF MCU_48MHZ == 0
|
|
subb A, #9Ah
|
|
ELSE
|
|
subb A, #34h
|
|
ENDIF
|
|
mov A, Temp4
|
|
IF MCU_48MHZ == 0
|
|
subb A, #03h
|
|
ELSE
|
|
subb A, #07h
|
|
ENDIF
|
|
jnc int0_int_check_full_range ; No - proceed
|
|
|
|
int0_int_outside_range:
|
|
inc Rcp_Outside_Range_Cnt
|
|
mov A, Rcp_Outside_Range_Cnt
|
|
jnz ($+4)
|
|
|
|
dec Rcp_Outside_Range_Cnt
|
|
|
|
clr C
|
|
mov A, Rcp_Outside_Range_Cnt
|
|
subb A, #50 ; Allow a given number of outside pulses
|
|
jnc ($+4)
|
|
ajmp int0_int_set_timeout ; If outside limits - ignore first pulses
|
|
|
|
mov New_Rcp, #0 ; Set pulse length to zero
|
|
ajmp int0_int_exit ; Exit without reseting timeout
|
|
|
|
int0_int_check_full_range:
|
|
; Decrement outside range counter
|
|
mov A, Rcp_Outside_Range_Cnt
|
|
jz ($+4)
|
|
|
|
dec Rcp_Outside_Range_Cnt
|
|
|
|
; Calculate "1000us" plus throttle minimum
|
|
jnb Flags2.RCP_FULL_RANGE, int0_int_set_min ; Check if full range is chosen
|
|
|
|
mov Temp5, #0 ; Set 1000us as default minimum
|
|
IF MCU_48MHZ == 0
|
|
mov Temp6, #4
|
|
ELSE
|
|
mov Temp6, #8
|
|
ENDIF
|
|
ajmp int0_int_calculate
|
|
|
|
int0_int_set_min:
|
|
mov Temp5, Min_Throttle_L ; Min throttle value scaled
|
|
mov Temp6, Min_Throttle_H
|
|
jnb Flags3.PGM_BIDIR, ($+7)
|
|
|
|
mov Temp5, Center_Throttle_L ; Center throttle value scaled
|
|
mov Temp6, Center_Throttle_H
|
|
|
|
int0_int_calculate:
|
|
clr C
|
|
mov A, Temp3 ; Subtract minimum
|
|
subb A, Temp5
|
|
mov Temp3, A
|
|
mov A, Temp4
|
|
subb A, Temp6
|
|
mov Temp4, A
|
|
mov Bit_Access_Int.0, C
|
|
mov Temp7, Throttle_Gain ; Load Temp7/Temp8 with throttle gain
|
|
mov Temp8, Throttle_Gain_M
|
|
jnb Flags3.PGM_BIDIR, int0_int_not_bidir ; If not bidirectional operation - branch
|
|
|
|
jnc int0_int_bidir_fwd ; If result is positive - branch
|
|
|
|
jb Flags2.RCP_DIR_REV, int0_int_bidir_rev_chk ; If same direction - branch
|
|
|
|
setb Flags2.RCP_DIR_REV
|
|
ajmp int0_int_bidir_rev_chk
|
|
|
|
int0_int_bidir_fwd:
|
|
jnb Flags2.RCP_DIR_REV, int0_int_bidir_rev_chk ; If same direction - branch
|
|
|
|
clr Flags2.RCP_DIR_REV
|
|
|
|
int0_int_bidir_rev_chk:
|
|
jnb Flags2.RCP_DIR_REV, ($+7)
|
|
|
|
mov Temp7, Throttle_Gain_BD_Rev ; Load Temp7/Temp8 with throttle gain for bidirectional reverse
|
|
mov Temp8, Throttle_Gain_BD_Rev_M
|
|
|
|
jb Flags3.PGM_BIDIR_REV, ($+5)
|
|
|
|
cpl Flags2.RCP_DIR_REV
|
|
|
|
clr C ; Multiply throttle value by 2
|
|
mov A, Temp3
|
|
rlc A
|
|
mov Temp3, A
|
|
mov A, Temp4
|
|
rlc A
|
|
mov Temp4, A
|
|
mov C, Bit_Access_Int.0
|
|
jnc int0_int_bidir_do_deadband ; If result is positive - branch
|
|
|
|
mov A, Temp3 ; Change sign
|
|
cpl A
|
|
add A, #1
|
|
mov Temp3, A
|
|
mov A, Temp4
|
|
cpl A
|
|
addc A, #0
|
|
mov Temp4, A
|
|
|
|
int0_int_bidir_do_deadband:
|
|
clr C ; Subtract deadband
|
|
mov A, Temp3
|
|
IF MCU_48MHZ == 0
|
|
subb A, #40
|
|
ELSE
|
|
subb A, #80
|
|
ENDIF
|
|
mov Temp3, A
|
|
mov A, Temp4
|
|
subb A, #0
|
|
mov Temp4, A
|
|
jnc int0_int_do_throttle_gain
|
|
|
|
mov Temp1, #0
|
|
mov Temp3, #0
|
|
mov Temp4, #0
|
|
ajmp int0_int_do_throttle_gain
|
|
|
|
int0_int_not_bidir:
|
|
mov C, Bit_Access_Int.0
|
|
jnc int0_int_do_throttle_gain ; If result is positive - branch
|
|
|
|
int0_int_unidir_neg:
|
|
mov Temp1, #0 ; Yes - set to minimum
|
|
mov Temp3, #0
|
|
mov Temp4, #0
|
|
ajmp int0_int_pulse_ready
|
|
|
|
int0_int_do_throttle_gain:
|
|
; Boost pwm during direct start
|
|
mov A, Flags1
|
|
anl A, #((1 SHL STARTUP_PHASE)+(1 SHL INITIAL_RUN_PHASE))
|
|
jz int0_int_startup_boosted
|
|
|
|
jb Flags1.MOTOR_STARTED, int0_int_startup_boosted ; Do not boost when changing direction in bidirectional mode
|
|
|
|
mov A, Pwm_Limit_Beg ; Set 25% of max startup power as minimum power
|
|
IF MCU_48MHZ == 1
|
|
rlc A
|
|
ENDIF
|
|
mov Temp2, A
|
|
mov A, Temp4
|
|
jnz int0_int_startup_boost_stall
|
|
|
|
clr C
|
|
mov A, Temp2
|
|
subb A, Temp3
|
|
jc int0_int_startup_boost_stall
|
|
|
|
mov A, Temp2
|
|
mov Temp3, A
|
|
|
|
int0_int_startup_boost_stall:
|
|
mov A, Stall_Cnt ; Add an extra power boost during start
|
|
swap A
|
|
IF MCU_48MHZ == 1
|
|
rlc A
|
|
ENDIF
|
|
add A, Temp3
|
|
mov Temp3, A
|
|
mov A, Temp4
|
|
addc A, #0
|
|
mov Temp4, A
|
|
|
|
int0_int_startup_boosted:
|
|
mov A, Temp3 ; Multiply throttle value by throttle gain
|
|
mov B, Temp7 ; Temp7 has Throttle_Gain
|
|
mul AB
|
|
mov Temp2, A
|
|
mov Temp3, B
|
|
mov A, Temp4
|
|
mov B, Temp7 ; Temp7 has Throttle_Gain
|
|
mul AB
|
|
add A, Temp3
|
|
mov Temp3, A
|
|
xch A, B
|
|
addc A, #0
|
|
mov Temp4, A
|
|
clr C ; Generate 8bit number
|
|
mov A, Temp4
|
|
rrc A
|
|
mov Temp6, A
|
|
mov A, Temp3
|
|
rrc A
|
|
mov Temp1, A
|
|
IF MCU_48MHZ == 1
|
|
clr C
|
|
mov A, Temp6
|
|
rrc A
|
|
mov Temp6, A
|
|
mov A, Temp1
|
|
rrc A
|
|
mov Temp1, A
|
|
ENDIF
|
|
inc Temp8 ; Temp8 has Throttle_Gain_M
|
|
int0_int_gain_loop:
|
|
mov A, Temp8
|
|
dec A
|
|
jz int0_int_gain_rcp_done ; Skip one multiply by 2 of New_Rcp
|
|
|
|
clr C
|
|
mov A, Temp1 ; Multiply New_Rcp by 2
|
|
rlc A
|
|
mov Temp1, A
|
|
|
|
int0_int_gain_rcp_done:
|
|
clr C
|
|
mov A, Temp2 ; Multiply pwm by 2
|
|
rlc A
|
|
mov A, Temp3
|
|
rlc A
|
|
mov Temp3, A
|
|
mov A, Temp4
|
|
rlc A
|
|
mov Temp4, A
|
|
djnz Temp8, int0_int_gain_loop
|
|
|
|
mov A, Temp4
|
|
IF MCU_48MHZ == 0
|
|
jnb ACC.2, int0_int_pulse_ready ; Check that RC pulse is within legal range
|
|
ELSE
|
|
jnb ACC.3, int0_int_pulse_ready
|
|
ENDIF
|
|
|
|
mov Temp1, #0FFh
|
|
mov Temp3, #0FFh
|
|
IF MCU_48MHZ == 0
|
|
mov Temp4, #3
|
|
ELSE
|
|
mov Temp4, #7
|
|
ENDIF
|
|
|
|
int0_int_pulse_ready:
|
|
mov New_Rcp, Temp1 ; Store new pulse length
|
|
setb Flags2.RCP_UPDATED ; Set updated flag
|
|
; Check if zero
|
|
mov A, Temp1 ; Load new pulse value
|
|
jz ($+5) ; Check if pulse is zero
|
|
|
|
mov Rcp_Stop_Cnt, #0 ; Reset rcp stop counter
|
|
|
|
; Set pwm limit
|
|
clr C
|
|
mov A, Pwm_Limit ; Limit to the smallest
|
|
mov Temp5, A ; Store limit in Temp5
|
|
subb A, Pwm_Limit_By_Rpm
|
|
jc ($+4)
|
|
|
|
mov Temp5, Pwm_Limit_By_Rpm
|
|
|
|
; Check against limit
|
|
clr C
|
|
mov A, Temp5
|
|
subb A, New_Rcp
|
|
jnc int0_int_set_pwm_registers
|
|
|
|
mov A, Temp5 ; Multiply limit by 4 (8 for 48MHz MCUs)
|
|
IF MCU_48MHZ == 0
|
|
mov B, #4
|
|
ELSE
|
|
mov B, #8
|
|
ENDIF
|
|
mul AB
|
|
mov Temp3, A
|
|
mov Temp4, B
|
|
|
|
int0_int_set_pwm_registers:
|
|
mov A, Temp3
|
|
cpl A
|
|
mov Temp1, A
|
|
mov A, Temp4
|
|
cpl A
|
|
IF MCU_48MHZ == 0
|
|
anl A, #3
|
|
ELSE
|
|
anl A, #7
|
|
ENDIF
|
|
mov Temp2, A
|
|
IF FETON_DELAY != 0
|
|
clr C
|
|
mov A, Temp1 ; Skew damping fet timing
|
|
IF MCU_48MHZ == 0
|
|
subb A, #FETON_DELAY
|
|
ELSE
|
|
subb A, #(FETON_DELAY SHL 1)
|
|
ENDIF
|
|
mov Temp3, A
|
|
mov A, Temp2
|
|
subb A, #0
|
|
mov Temp4, A
|
|
jnc int0_int_set_pwm_damp_set
|
|
|
|
mov Temp3, #0
|
|
mov Temp4, #0
|
|
|
|
int0_int_set_pwm_damp_set:
|
|
ENDIF
|
|
mov Power_Pwm_Reg_L, Temp1
|
|
mov Power_Pwm_Reg_H, Temp2
|
|
IF FETON_DELAY != 0
|
|
mov Damp_Pwm_Reg_L, Temp3
|
|
mov Damp_Pwm_Reg_H, Temp4
|
|
ENDIF
|
|
mov Rcp_Timeout_Cntd, #10 ; Set timeout count
|
|
IF FETON_DELAY != 0
|
|
pop B ; Restore preserved registers
|
|
pop ACC
|
|
pop PSW
|
|
Clear_COVF_Interrupt
|
|
Enable_COVF_Interrupt ; Generate a pca interrupt
|
|
orl EIE1, #10h ; Enable pca interrupts
|
|
reti
|
|
ELSE
|
|
mov A, Current_Power_Pwm_Reg_H
|
|
IF MCU_48MHZ == 0
|
|
jnb ACC.1, int0_int_set_pca_int_hi_pwm
|
|
ELSE
|
|
jnb ACC.2, int0_int_set_pca_int_hi_pwm
|
|
ENDIF
|
|
|
|
pop B ; Restore preserved registers
|
|
pop ACC
|
|
pop PSW
|
|
Clear_COVF_Interrupt
|
|
Enable_COVF_Interrupt ; Generate a pca interrupt
|
|
orl EIE1, #10h ; Enable pca interrupts
|
|
reti
|
|
|
|
int0_int_set_pca_int_hi_pwm:
|
|
pop B ; Restore preserved registers
|
|
pop ACC
|
|
pop PSW
|
|
Clear_CCF_Interrupt
|
|
Enable_CCF_Interrupt ; Generate pca interrupt
|
|
orl EIE1, #10h ; Enable pca interrupts
|
|
reti
|
|
ENDIF
|
|
|
|
int0_int_set_timeout:
|
|
mov Rcp_Timeout_Cntd, #10 ; Set timeout count
|
|
int0_int_exit:
|
|
pop B ; Restore preserved registers
|
|
pop ACC
|
|
pop PSW
|
|
orl EIE1, #10h ; Enable pca interrupts
|
|
reti
|
|
|
|
|
|
;**** **** **** **** **** **** **** **** **** **** **** **** ****
|
|
;
|
|
; Int1 interrupt routine
|
|
;
|
|
; No assumptions
|
|
;
|
|
;**** **** **** **** **** **** **** **** **** **** **** **** ****
|
|
int1_int: ; Used for RC pulse timing
|
|
clr IE_EX1 ; Disable int1 interrupts
|
|
setb TCON_TR1 ; Start timer 1
|
|
clr TMR2CN0_TR2 ; Timer 2 disabled
|
|
mov DShot_Frame_Start_L, TMR2L ; Read timer value
|
|
mov DShot_Frame_Start_H, TMR2H
|
|
setb TMR2CN0_TR2 ; Timer 2 enabled
|
|
reti
|
|
|
|
|
|
;**** **** **** **** **** **** **** **** **** **** **** **** ****
|
|
;
|
|
; PCA interrupt routine
|
|
;
|
|
; No assumptions
|
|
;
|
|
;**** **** **** **** **** **** **** **** **** **** **** **** ****
|
|
pca_int: ; Used for setting pwm registers
|
|
clr IE_EA
|
|
push PSW ; Preserve registers through interrupt
|
|
push ACC
|
|
setb PSW.3 ; Select register bank 1 for this interrupt
|
|
|
|
IF FETON_DELAY != 0 ; HI/LO enable style drivers
|
|
|
|
mov Temp1, PCA0L ; Read low byte, to transfer high byte to holding register
|
|
mov A, Current_Power_Pwm_Reg_H
|
|
IF MCU_48MHZ == 0
|
|
jnb ACC.1, pca_int_hi_pwm
|
|
ELSE
|
|
jnb ACC.2, pca_int_hi_pwm
|
|
ENDIF
|
|
mov A, PCA0H
|
|
IF MCU_48MHZ == 0
|
|
jb ACC.1, pca_int_exit ; Power below 50%, update pca in the 0x00-0x0F range
|
|
jb ACC.0, pca_int_exit
|
|
ELSE
|
|
jb ACC.2, pca_int_exit
|
|
jb ACC.1, pca_int_exit
|
|
ENDIF
|
|
ajmp pca_int_set_pwm
|
|
|
|
pca_int_hi_pwm:
|
|
mov A, PCA0H
|
|
IF MCU_48MHZ == 0
|
|
jnb ACC.1, pca_int_exit ; Power above 50%, update pca in the 0x20-0x2F range
|
|
jb ACC.0, pca_int_exit
|
|
ELSE
|
|
jnb ACC.2, pca_int_exit
|
|
jb ACC.1, pca_int_exit
|
|
ENDIF
|
|
|
|
pca_int_set_pwm:
|
|
Set_Power_Pwm_Regs
|
|
Set_Damp_Pwm_Regs
|
|
mov Current_Power_Pwm_Reg_H, Power_Pwm_Reg_H
|
|
Disable_COVF_Interrupt
|
|
|
|
ELSE ; EN/PWM style drivers
|
|
Set_Power_Pwm_Regs
|
|
mov Current_Power_Pwm_Reg_H, Power_Pwm_Reg_H
|
|
Disable_COVF_Interrupt
|
|
Disable_CCF_Interrupt
|
|
|
|
ENDIF
|
|
|
|
; Pwm updated, enable/disable interrupts
|
|
setb IE_EX0 ; Enable int0 interrupts
|
|
jnb Flags2.RCP_DSHOT, ($+5)
|
|
setb IE_EX1 ; Enable int1 interrupts (DShot only)
|
|
anl EIE1, #0EFh ; Disable pca interrupts
|
|
pca_int_exit:
|
|
Clear_COVF_Interrupt
|
|
IF FETON_DELAY == 0
|
|
Clear_CCF_Interrupt
|
|
ENDIF
|
|
pop ACC ; Restore preserved registers
|
|
pop PSW
|
|
setb IE_EA
|
|
reti
|
|
|
|
|
|
;**** **** **** **** **** **** **** **** **** **** **** **** ****
|
|
;
|
|
; Wait xms ~(x*4*250) (Different entry points)
|
|
;
|
|
; No assumptions
|
|
;
|
|
;**** **** **** **** **** **** **** **** **** **** **** **** ****
|
|
wait1ms:
|
|
mov Temp2, #1
|
|
jmp waitxms_o
|
|
|
|
wait3ms:
|
|
mov Temp2, #3
|
|
jmp waitxms_o
|
|
|
|
wait10ms:
|
|
mov Temp2, #10
|
|
jmp waitxms_o
|
|
|
|
wait30ms:
|
|
mov Temp2, #30
|
|
jmp waitxms_o
|
|
|
|
wait100ms:
|
|
mov Temp2, #100
|
|
jmp waitxms_o
|
|
|
|
wait200ms:
|
|
mov Temp2, #200
|
|
jmp waitxms_o
|
|
|
|
waitxms_o: ; Outer loop
|
|
mov Temp1, #23
|
|
waitxms_m: ; Middle loop
|
|
clr A
|
|
djnz ACC, $ ; Inner loop (42.7us - 1024 cycles)
|
|
djnz Temp1, waitxms_m
|
|
djnz Temp2, waitxms_o
|
|
ret
|
|
|
|
;**** **** **** **** **** **** **** **** **** **** **** **** ****
|
|
;
|
|
; Set pwm limit low rpm
|
|
;
|
|
; No assumptions
|
|
;
|
|
; Sets power limit for low rpms and disables demag for low rpms
|
|
;
|
|
;**** **** **** **** **** **** **** **** **** **** **** **** ****
|
|
set_pwm_limit_low_rpm:
|
|
; Set pwm limit
|
|
mov Temp1, #0FFh ; Default full power
|
|
jb Flags1.STARTUP_PHASE, set_pwm_limit_low_rpm_exit ; Exit if startup phase set
|
|
|
|
mov Temp2, #Pgm_Enable_Power_Prot ; Check if low RPM power protection is enabled
|
|
mov A, @Temp2
|
|
jz set_pwm_limit_low_rpm_exit ; Exit if disabled
|
|
|
|
mov A, Comm_Period4x_H
|
|
jz set_pwm_limit_low_rpm_exit ; Avoid divide by zero
|
|
|
|
mov A, #255 ; Divide 255 by Comm_Period4x_H
|
|
mov B, Comm_Period4x_H
|
|
div AB
|
|
mov B, Low_Rpm_Pwr_Slope ; Multiply by slope
|
|
jnb Flags1.INITIAL_RUN_PHASE, ($+6) ; More protection for initial run phase
|
|
mov B, #5
|
|
mul AB
|
|
mov Temp1, A ; Set new limit
|
|
xch A, B
|
|
jz ($+4) ; Limit to max
|
|
|
|
mov Temp1, #0FFh
|
|
|
|
clr C
|
|
mov A, Temp1 ; Limit to min
|
|
subb A, Pwm_Limit_Beg
|
|
jnc set_pwm_limit_low_rpm_exit
|
|
|
|
mov Temp1, Pwm_Limit_Beg
|
|
|
|
set_pwm_limit_low_rpm_exit:
|
|
mov Pwm_Limit_By_Rpm, Temp1
|
|
ret
|
|
|
|
|
|
;**** **** **** **** **** **** **** **** **** **** **** **** ****
|
|
;
|
|
; Set pwm limit high rpm
|
|
;
|
|
; No assumptions
|
|
;
|
|
; Sets power limit for high rpms
|
|
;
|
|
;**** **** **** **** **** **** **** **** **** **** **** **** ****
|
|
set_pwm_limit_high_rpm:
|
|
IF MCU_48MHZ == 1
|
|
clr C
|
|
mov A, Comm_Period4x_L
|
|
subb A, #0A0h ; Limit Comm_Period to 160, which is 500k erpm
|
|
mov A, Comm_Period4x_H
|
|
subb A, #00h
|
|
ELSE
|
|
clr C
|
|
mov A, Comm_Period4x_L
|
|
subb A, #0E4h ; Limit Comm_Period to 228, which is 350k erpm
|
|
mov A, Comm_Period4x_H
|
|
subb A, #00h
|
|
ENDIF
|
|
mov A, Pwm_Limit_By_Rpm
|
|
jnc set_pwm_limit_high_rpm_inc_limit
|
|
|
|
dec A
|
|
ajmp set_pwm_limit_high_rpm_store
|
|
|
|
set_pwm_limit_high_rpm_inc_limit:
|
|
inc A
|
|
set_pwm_limit_high_rpm_store:
|
|
jz ($+4)
|
|
|
|
mov Pwm_Limit_By_Rpm, A
|
|
|
|
ret
|
|
|
|
|
|
;**** **** **** **** **** **** **** **** **** **** **** **** ****
|
|
;
|
|
; Start ADC conversion
|
|
;
|
|
; No assumptions
|
|
;
|
|
; Start conversion used for measuring power supply voltage
|
|
;
|
|
;**** **** **** **** **** **** **** **** **** **** **** **** ****
|
|
start_adc_conversion:
|
|
; Start adc
|
|
Start_Adc
|
|
ret
|
|
|
|
|
|
;**** **** **** **** **** **** **** **** **** **** **** **** ****
|
|
;
|
|
; Check temperature, power supply voltage and limit power
|
|
;
|
|
; No assumptions
|
|
;
|
|
; Used to limit main motor power in order to maintain the required voltage
|
|
;
|
|
;**** **** **** **** **** **** **** **** **** **** **** **** ****
|
|
check_temp_voltage_and_limit_power:
|
|
inc Adc_Conversion_Cnt ; Increment conversion counter
|
|
clr C
|
|
mov A, Adc_Conversion_Cnt ; Is conversion count equal to temp rate?
|
|
subb A, #8
|
|
jc check_voltage_start ; No - check voltage
|
|
|
|
; Wait for ADC conversion to complete
|
|
jnb ADC0CN0_ADINT, check_temp_voltage_and_limit_power
|
|
; Read ADC result
|
|
Read_Adc_Result
|
|
; Stop ADC
|
|
Stop_Adc
|
|
|
|
mov Adc_Conversion_Cnt, #0 ; Yes - temperature check. Reset counter
|
|
mov A, Temp2 ; Move ADC MSB to Temp3
|
|
mov Temp3, A
|
|
mov Temp2, #Pgm_Enable_Temp_Prot ; Is temp protection enabled?
|
|
mov A, @Temp2
|
|
jz temp_check_exit ; No - branch
|
|
|
|
mov A, Temp3 ; Is temperature reading below 256?
|
|
jnz temp_average_inc_dec ; No - proceed
|
|
|
|
mov A, Current_Average_Temp ; Yes - decrement average
|
|
jz temp_average_updated ; Already zero - no change
|
|
jmp temp_average_dec ; Decrement
|
|
|
|
temp_average_inc_dec:
|
|
clr C
|
|
mov A, Temp1 ; Check if current temperature is above or below average
|
|
subb A, Current_Average_Temp
|
|
jz temp_average_updated_load_acc ; Equal - no change
|
|
|
|
mov A, Current_Average_Temp ; Above - increment average
|
|
jnc temp_average_inc
|
|
|
|
jz temp_average_updated ; Below - decrement average if average is not already zero
|
|
temp_average_dec:
|
|
dec A ; Decrement average
|
|
jmp temp_average_updated
|
|
|
|
temp_average_inc:
|
|
inc A ; Increment average
|
|
jz temp_average_dec
|
|
jmp temp_average_updated
|
|
|
|
temp_average_updated_load_acc:
|
|
mov A, Current_Average_Temp
|
|
temp_average_updated:
|
|
mov Current_Average_Temp, A
|
|
clr C
|
|
subb A, Temp_Prot_Limit ; Is temperature below first limit?
|
|
jc temp_check_exit ; Yes - exit
|
|
|
|
mov Pwm_Limit, #192 ; No - limit pwm
|
|
|
|
clr C
|
|
subb A, #(TEMP_LIMIT_STEP/2) ; Is temperature below second limit
|
|
jc temp_check_exit ; Yes - exit
|
|
|
|
mov Pwm_Limit, #128 ; No - limit pwm
|
|
|
|
clr C
|
|
subb A, #(TEMP_LIMIT_STEP/2) ; Is temperature below third limit
|
|
jc temp_check_exit ; Yes - exit
|
|
|
|
mov Pwm_Limit, #64 ; No - limit pwm
|
|
|
|
clr C
|
|
subb A, #(TEMP_LIMIT_STEP/2) ; Is temperature below final limit
|
|
jc temp_check_exit ; Yes - exit
|
|
|
|
mov Pwm_Limit, #0 ; No - limit pwm
|
|
|
|
temp_check_exit:
|
|
ret
|
|
|
|
check_voltage_start:
|
|
; Increase pwm limit
|
|
mov A, Pwm_Limit
|
|
add A, #16
|
|
jnc ($+4) ; If not max - branch
|
|
|
|
mov A, #255
|
|
|
|
mov Pwm_Limit, A ; Increment limit
|
|
ret
|
|
|
|
|
|
;**** **** **** **** **** **** **** **** **** **** **** **** ****
|
|
;
|
|
; Set startup PWM routine
|
|
;
|
|
; Either the SETTLE_PHASE or the STEPPER_PHASE flag must be set
|
|
;
|
|
; Used for pwm control during startup
|
|
;
|
|
;**** **** **** **** **** **** **** **** **** **** **** **** ****
|
|
set_startup_pwm:
|
|
; Adjust startup power
|
|
mov A, #50 ; Set power
|
|
mov Temp2, #Pgm_Startup_Pwr_Decoded
|
|
mov B, @Temp2
|
|
mul AB
|
|
xch A, B
|
|
mov C, B.7 ; Multiply result by 2 (unity gain is 128)
|
|
rlc A
|
|
mov Pwm_Limit_Beg, A ; Set initial pwm limit
|
|
ret
|
|
|
|
|
|
;**** **** **** **** **** **** **** **** **** **** **** **** ****
|
|
;
|
|
; Initialize timing routine
|
|
;
|
|
; No assumptions
|
|
;
|
|
; Part of initialization before motor start
|
|
;
|
|
;**** **** **** **** **** **** **** **** **** **** **** **** ****
|
|
initialize_timing:
|
|
mov Comm_Period4x_L, #00h ; Set commutation period registers
|
|
mov Comm_Period4x_H, #0F0h
|
|
ret
|
|
|
|
|
|
;**** **** **** **** **** **** **** **** **** **** **** **** ****
|
|
;
|
|
; Calculate next commutation timing routine
|
|
;
|
|
; No assumptions
|
|
;
|
|
; Called immediately after each commutation
|
|
; Also sets up timer 3 to wait advance timing
|
|
; Two entry points are used
|
|
;
|
|
;**** **** **** **** **** **** **** **** **** **** **** **** ****
|
|
calc_next_comm_timing: ; Entry point for run phase
|
|
; Read commutation time
|
|
clr IE_EA
|
|
clr TMR2CN0_TR2 ; Timer 2 disabled
|
|
mov Temp1, TMR2L ; Load timer value
|
|
mov Temp2, TMR2H
|
|
mov Temp3, Timer2_X
|
|
jnb TMR2CN0_TF2H, ($+4) ; Check if interrupt is pending
|
|
inc Temp3 ; If it is pending, then timer has already wrapped
|
|
setb TMR2CN0_TR2 ; Timer 2 enabled
|
|
setb IE_EA
|
|
IF MCU_48MHZ == 1
|
|
clr C
|
|
mov A, Temp3
|
|
rrc A
|
|
mov Temp3, A
|
|
mov A, Temp2
|
|
rrc A
|
|
mov Temp2, A
|
|
mov A, Temp1
|
|
rrc A
|
|
mov Temp1, A
|
|
ENDIF
|
|
; Calculate this commutation time
|
|
mov Temp4, Prev_Comm_L
|
|
mov Temp5, Prev_Comm_H
|
|
mov Prev_Comm_L, Temp1 ; Store timestamp as previous commutation
|
|
mov Prev_Comm_H, Temp2
|
|
clr C
|
|
mov A, Temp1
|
|
subb A, Temp4 ; Calculate the new commutation time
|
|
mov Temp1, A
|
|
mov A, Temp2
|
|
subb A, Temp5
|
|
jb Flags1.STARTUP_PHASE, calc_next_comm_startup
|
|
|
|
IF MCU_48MHZ == 1
|
|
anl A, #7Fh
|
|
ENDIF
|
|
mov Temp2, A
|
|
jnb Flags1.HIGH_RPM, ($+5) ; Branch if high rpm
|
|
ajmp calc_next_comm_timing_fast
|
|
|
|
ajmp calc_next_comm_normal
|
|
|
|
calc_next_comm_startup:
|
|
mov Temp6, Prev_Comm_X
|
|
mov Prev_Comm_X, Temp3 ; Store extended timestamp as previous commutation
|
|
mov Temp2, A
|
|
mov A, Temp3
|
|
subb A, Temp6 ; Calculate the new extended commutation time
|
|
IF MCU_48MHZ == 1
|
|
anl A, #7Fh
|
|
ENDIF
|
|
mov Temp3, A
|
|
jz calc_next_comm_startup_no_X
|
|
|
|
mov Temp1, #0FFh
|
|
mov Temp2, #0FFh
|
|
ajmp calc_next_comm_startup_average
|
|
|
|
calc_next_comm_startup_no_X:
|
|
mov Temp7, Prev_Prev_Comm_L
|
|
mov Temp8, Prev_Prev_Comm_H
|
|
mov Prev_Prev_Comm_L, Temp4
|
|
mov Prev_Prev_Comm_H, Temp5
|
|
mov Temp1, Prev_Comm_L ; Reload this commutation time
|
|
mov Temp2, Prev_Comm_H
|
|
clr C
|
|
mov A, Temp1
|
|
subb A, Temp7 ; Calculate the new commutation time based upon the two last commutations (to reduce sensitivity to offset)
|
|
mov Temp1, A
|
|
mov A, Temp2
|
|
subb A, Temp8
|
|
mov Temp2, A
|
|
|
|
calc_next_comm_startup_average:
|
|
clr C
|
|
mov A, Comm_Period4x_H ; Average with previous and save
|
|
rrc A
|
|
mov Temp4, A
|
|
mov A, Comm_Period4x_L
|
|
rrc A
|
|
mov Temp3, A
|
|
mov A, Temp1
|
|
add A, Temp3
|
|
mov Comm_Period4x_L, A
|
|
mov A, Temp2
|
|
addc A, Temp4
|
|
mov Comm_Period4x_H, A
|
|
jnc ($+8)
|
|
|
|
mov Comm_Period4x_L, #0FFh
|
|
mov Comm_Period4x_H, #0FFh
|
|
|
|
ajmp calc_new_wait_times_setup
|
|
|
|
calc_next_comm_normal:
|
|
; Calculate new commutation time
|
|
mov Temp3, Comm_Period4x_L ; Comm_Period4x(-l-h) holds the time of 4 commutations
|
|
mov Temp4, Comm_Period4x_H
|
|
mov Temp5, Comm_Period4x_L ; Copy variables
|
|
mov Temp6, Comm_Period4x_H
|
|
mov Temp7, #4 ; Divide Comm_Period4x 4 times as default
|
|
mov Temp8, #2 ; Divide new commutation time 2 times as default
|
|
clr C
|
|
mov A, Temp4
|
|
subb A, #04h
|
|
jc calc_next_comm_avg_period_div
|
|
|
|
dec Temp7 ; Reduce averaging time constant for low speeds
|
|
dec Temp8
|
|
|
|
clr C
|
|
mov A, Temp4
|
|
subb A, #08h
|
|
jc calc_next_comm_avg_period_div
|
|
|
|
jb Flags1.INITIAL_RUN_PHASE, calc_next_comm_avg_period_div ; Do not average very fast during initial run
|
|
|
|
dec Temp7 ; Reduce averaging time constant more for even lower speeds
|
|
dec Temp8
|
|
|
|
calc_next_comm_avg_period_div:
|
|
clr C
|
|
mov A, Temp6
|
|
rrc A ; Divide by 2
|
|
mov Temp6, A
|
|
mov A, Temp5
|
|
rrc A
|
|
mov Temp5, A
|
|
djnz Temp7, calc_next_comm_avg_period_div
|
|
|
|
clr C
|
|
mov A, Temp3
|
|
subb A, Temp5 ; Subtract a fraction
|
|
mov Temp3, A
|
|
mov A, Temp4
|
|
subb A, Temp6
|
|
mov Temp4, A
|
|
mov A, Temp8 ; Divide new time
|
|
jz calc_next_comm_new_period_div_done
|
|
|
|
calc_next_comm_new_period_div:
|
|
clr C
|
|
mov A, Temp2
|
|
rrc A ; Divide by 2
|
|
mov Temp2, A
|
|
mov A, Temp1
|
|
rrc A
|
|
mov Temp1, A
|
|
djnz Temp8, calc_next_comm_new_period_div
|
|
|
|
calc_next_comm_new_period_div_done:
|
|
mov A, Temp3
|
|
add A, Temp1 ; Add the divided new time
|
|
mov Temp3, A
|
|
mov A, Temp4
|
|
addc A, Temp2
|
|
mov Temp4, A
|
|
mov Comm_Period4x_L, Temp3 ; Store Comm_Period4x_X
|
|
mov Comm_Period4x_H, Temp4
|
|
jnc calc_new_wait_times_setup; If period larger than 0xffff - go to slow case
|
|
|
|
mov Temp4, #0FFh
|
|
mov Comm_Period4x_L, Temp4 ; Set commutation period registers to very slow timing (0xffff)
|
|
mov Comm_Period4x_H, Temp4
|
|
|
|
calc_new_wait_times_setup:
|
|
; Set high rpm bit (if above 156k erpm)
|
|
clr C
|
|
mov A, Temp4
|
|
subb A, #2
|
|
jnc ($+4)
|
|
|
|
setb Flags1.HIGH_RPM ; Set high rpm bit
|
|
|
|
; Load programmed commutation timing
|
|
jnb Flags1.STARTUP_PHASE, calc_new_wait_per_startup_done ; Set dedicated timing during startup
|
|
|
|
mov Temp8, #3
|
|
ajmp calc_new_wait_per_demag_done
|
|
|
|
calc_new_wait_per_startup_done:
|
|
mov Temp1, #Pgm_Comm_Timing ; Load timing setting
|
|
mov A, @Temp1
|
|
mov Temp8, A ; Store in Temp8
|
|
clr C
|
|
mov A, Demag_Detected_Metric ; Check demag metric
|
|
subb A, #130
|
|
jc calc_new_wait_per_demag_done
|
|
|
|
inc Temp8 ; Increase timing
|
|
|
|
clr C
|
|
mov A, Demag_Detected_Metric
|
|
subb A, #160
|
|
jc ($+3)
|
|
|
|
inc Temp8 ; Increase timing again
|
|
|
|
clr C
|
|
mov A, Temp8 ; Limit timing to max
|
|
subb A, #6
|
|
jc ($+4)
|
|
|
|
mov Temp8, #5 ; Set timing to max
|
|
|
|
calc_new_wait_per_demag_done:
|
|
; Set timing reduction
|
|
mov Temp7, #2
|
|
; Load current commutation timing
|
|
mov A, Comm_Period4x_H ; Divide 4 times
|
|
swap A
|
|
anl A, #00Fh
|
|
mov Temp2, A
|
|
mov A, Comm_Period4x_H
|
|
swap A
|
|
anl A, #0F0h
|
|
mov Temp1, A
|
|
mov A, Comm_Period4x_L
|
|
swap A
|
|
anl A, #00Fh
|
|
add A, Temp1
|
|
mov Temp1, A
|
|
|
|
clr C
|
|
mov A, Temp1
|
|
subb A, Temp7
|
|
mov Temp3, A
|
|
mov A, Temp2
|
|
subb A, #0
|
|
mov Temp4, A
|
|
jc load_min_time ; Check that result is still positive
|
|
|
|
clr C
|
|
mov A, Temp3
|
|
subb A, #1
|
|
mov A, Temp4
|
|
subb A, #0
|
|
jnc calc_new_wait_times_exit ; Check that result is still above minumum
|
|
|
|
load_min_time:
|
|
mov Temp3, #1
|
|
clr A
|
|
mov Temp4, A
|
|
|
|
calc_new_wait_times_exit:
|
|
ljmp wait_advance_timing
|
|
|
|
|
|
; Fast calculation (Comm_Period4x_H less than 2)
|
|
calc_next_comm_timing_fast:
|
|
; Calculate new commutation time
|
|
mov Temp3, Comm_Period4x_L ; Comm_Period4x(-l-h) holds the time of 4 commutations
|
|
mov Temp4, Comm_Period4x_H
|
|
mov A, Temp4 ; Divide by 2 4 times
|
|
swap A
|
|
mov Temp7, A
|
|
mov A, Temp3
|
|
swap A
|
|
anl A, #0Fh
|
|
orl A, Temp7
|
|
mov Temp5, A
|
|
clr C
|
|
mov A, Temp3 ; Subtract a fraction
|
|
subb A, Temp5
|
|
mov Temp3, A
|
|
mov A, Temp4
|
|
subb A, #0
|
|
mov Temp4, A
|
|
clr C
|
|
mov A, Temp1
|
|
rrc A ; Divide by 2 2 times
|
|
clr C
|
|
rrc A
|
|
mov Temp1, A
|
|
mov A, Temp3 ; Add the divided new time
|
|
add A, Temp1
|
|
mov Temp3, A
|
|
mov A, Temp4
|
|
addc A, #0
|
|
mov Temp4, A
|
|
mov Comm_Period4x_L, Temp3 ; Store Comm_Period4x_X
|
|
mov Comm_Period4x_H, Temp4
|
|
clr C
|
|
mov A, Temp4 ; If erpm below 156k - go to normal case
|
|
subb A, #2
|
|
jc ($+4)
|
|
|
|
clr Flags1.HIGH_RPM ; Clear high rpm bit
|
|
|
|
; Set timing reduction
|
|
mov Temp1, #2
|
|
mov A, Temp4 ; Divide by 2 4 times
|
|
swap A
|
|
mov Temp7, A
|
|
mov Temp4, #0
|
|
mov A, Temp3
|
|
swap A
|
|
anl A, #0Fh
|
|
orl A, Temp7
|
|
mov Temp3, A
|
|
clr C
|
|
mov A, Temp3
|
|
subb A, Temp1
|
|
mov Temp3, A
|
|
jc load_min_time_fast ; Check that result is still positive
|
|
|
|
clr C
|
|
subb A, #1
|
|
jnc calc_new_wait_times_fast_done ; Check that result is still above minumum
|
|
|
|
load_min_time_fast:
|
|
mov Temp3, #1
|
|
|
|
calc_new_wait_times_fast_done:
|
|
mov Temp1, #Pgm_Comm_Timing ; Load timing setting
|
|
mov A, @Temp1
|
|
mov Temp8, A ; Store in Temp8
|
|
|
|
|
|
;**** **** **** **** **** **** **** **** **** **** **** **** ****
|
|
;
|
|
; Wait advance timing routine
|
|
;
|
|
; No assumptions
|
|
; NOTE: Be VERY careful if using temp registers. They are passed over this routine
|
|
;
|
|
; Waits for the advance timing to elapse and sets up the next zero cross wait
|
|
;
|
|
;**** **** **** **** **** **** **** **** **** **** **** **** ****
|
|
wait_advance_timing:
|
|
jnb Flags0.T3_PENDING, ($+5)
|
|
ajmp wait_advance_timing
|
|
|
|
; Setup next wait time
|
|
mov TMR3RLL, Wt_ZC_Tout_Start_L
|
|
mov TMR3RLH, Wt_ZC_Tout_Start_H
|
|
setb Flags0.T3_PENDING
|
|
orl EIE1, #80h ; Enable timer 3 interrupts
|
|
|
|
|
|
;**** **** **** **** **** **** **** **** **** **** **** **** ****
|
|
;
|
|
; Calculate new wait times routine
|
|
;
|
|
; No assumptions
|
|
;
|
|
; Calculates new wait times
|
|
;
|
|
;**** **** **** **** **** **** **** **** **** **** **** **** ****
|
|
calc_new_wait_times:
|
|
clr C
|
|
clr A
|
|
subb A, Temp3 ; Negate
|
|
mov Temp1, A
|
|
clr A
|
|
subb A, Temp4
|
|
mov Temp2, A
|
|
IF MCU_48MHZ == 1
|
|
clr C
|
|
mov A, Temp1 ; Multiply by 2
|
|
rlc A
|
|
mov Temp1, A
|
|
mov A, Temp2
|
|
rlc A
|
|
mov Temp2, A
|
|
ENDIF
|
|
jnb Flags1.HIGH_RPM, ($+6) ; Branch if high rpm
|
|
ljmp calc_new_wait_times_fast
|
|
|
|
mov A, Temp1 ; Copy values
|
|
mov Temp3, A
|
|
mov A, Temp2
|
|
mov Temp4, A
|
|
setb C ; Negative numbers - set carry
|
|
mov A, Temp2
|
|
rrc A ; Divide by 2
|
|
mov Temp6, A
|
|
mov A, Temp1
|
|
rrc A
|
|
mov Temp5, A
|
|
mov Wt_Zc_Tout_Start_L, Temp1; Set 15deg time for zero cross scan timeout
|
|
mov Wt_Zc_Tout_Start_H, Temp2
|
|
clr C
|
|
mov A, Temp8 ; (Temp8 has Pgm_Comm_Timing)
|
|
subb A, #3 ; Is timing normal?
|
|
jz store_times_decrease ; Yes - branch
|
|
|
|
mov A, Temp8
|
|
jb ACC.0, adjust_timing_two_steps ; If an odd number - branch
|
|
|
|
mov A, Temp1 ; Add 7.5deg and store in Temp1/2
|
|
add A, Temp5
|
|
mov Temp1, A
|
|
mov A, Temp2
|
|
addc A, Temp6
|
|
mov Temp2, A
|
|
mov A, Temp5 ; Store 7.5deg in Temp3/4
|
|
mov Temp3, A
|
|
mov A, Temp6
|
|
mov Temp4, A
|
|
jmp store_times_up_or_down
|
|
|
|
adjust_timing_two_steps:
|
|
mov A, Temp1 ; Add 15deg and store in Temp1/2
|
|
add A, Temp1
|
|
mov Temp1, A
|
|
mov A, Temp2
|
|
addc A, Temp2
|
|
mov Temp2, A
|
|
clr C
|
|
mov A, Temp1
|
|
add A, #1
|
|
mov Temp1, A
|
|
mov A, Temp2
|
|
addc A, #0
|
|
mov Temp2, A
|
|
mov Temp3, #-1 ; Store minimum time in Temp3/4
|
|
mov Temp4, #0FFh
|
|
|
|
store_times_up_or_down:
|
|
clr C
|
|
mov A, Temp8
|
|
subb A, #3 ; Is timing higher than normal?
|
|
jc store_times_decrease ; No - branch
|
|
|
|
store_times_increase:
|
|
mov Wt_Comm_Start_L, Temp3 ; Now commutation time (~60deg) divided by 4 (~15deg nominal)
|
|
mov Wt_Comm_Start_H, Temp4
|
|
mov Wt_Adv_Start_L, Temp1 ; New commutation advance time (~15deg nominal)
|
|
mov Wt_Adv_Start_H, Temp2
|
|
mov Wt_Zc_Scan_Start_L, Temp5 ; Use this value for zero cross scan delay (7.5deg)
|
|
mov Wt_Zc_Scan_Start_H, Temp6
|
|
ljmp wait_before_zc_scan
|
|
|
|
store_times_decrease:
|
|
mov Wt_Comm_Start_L, Temp1 ; Now commutation time (~60deg) divided by 4 (~15deg nominal)
|
|
mov Wt_Comm_Start_H, Temp2
|
|
mov Wt_Adv_Start_L, Temp3 ; New commutation advance time (~15deg nominal)
|
|
mov Wt_Adv_Start_H, Temp4
|
|
mov Wt_Zc_Scan_Start_L, Temp5 ; Use this value for zero cross scan delay (7.5deg)
|
|
mov Wt_Zc_Scan_Start_H, Temp6
|
|
jnb Flags1.STARTUP_PHASE, store_times_exit
|
|
|
|
mov Wt_Comm_Start_L, #0F0h ; Set very short delays for all but advance time during startup, in order to widen zero cross capture range
|
|
mov Wt_Comm_Start_H, #0FFh
|
|
mov Wt_Zc_Scan_Start_L, #0F0h
|
|
mov Wt_Zc_Scan_Start_H, #0FFh
|
|
mov Wt_Zc_Tout_Start_L, #0F0h
|
|
mov Wt_Zc_Tout_Start_H, #0FFh
|
|
|
|
store_times_exit:
|
|
ljmp wait_before_zc_scan
|
|
|
|
|
|
calc_new_wait_times_fast:
|
|
mov A, Temp1 ; Copy values
|
|
mov Temp3, A
|
|
setb C ; Negative numbers - set carry
|
|
mov A, Temp1 ; Divide by 2
|
|
rrc A
|
|
mov Temp5, A
|
|
mov Wt_Zc_Tout_Start_L, Temp1; Set 15deg time for zero cross scan timeout
|
|
clr C
|
|
mov A, Temp8 ; (Temp8 has Pgm_Comm_Timing)
|
|
subb A, #3 ; Is timing normal?
|
|
jz store_times_decrease_fast; Yes - branch
|
|
|
|
mov A, Temp8
|
|
jb ACC.0, adjust_timing_two_steps_fast ; If an odd number - branch
|
|
|
|
mov A, Temp1 ; Add 7.5deg and store in Temp1
|
|
add A, Temp5
|
|
mov Temp1, A
|
|
mov A, Temp5 ; Store 7.5deg in Temp3
|
|
mov Temp3, A
|
|
ajmp store_times_up_or_down_fast
|
|
|
|
adjust_timing_two_steps_fast:
|
|
mov A, Temp1 ; Add 15deg and store in Temp1
|
|
add A, Temp1
|
|
add A, #1
|
|
mov Temp1, A
|
|
mov Temp3, #-1 ; Store minimum time in Temp3
|
|
|
|
store_times_up_or_down_fast:
|
|
clr C
|
|
mov A, Temp8
|
|
subb A, #3 ; Is timing higher than normal?
|
|
jc store_times_decrease_fast; No - branch
|
|
|
|
store_times_increase_fast:
|
|
mov Wt_Comm_Start_L, Temp3 ; Now commutation time (~60deg) divided by 4 (~15deg nominal)
|
|
mov Wt_Adv_Start_L, Temp1 ; New commutation advance time (~15deg nominal)
|
|
mov Wt_Zc_Scan_Start_L, Temp5 ; Use this value for zero cross scan delay (7.5deg)
|
|
ljmp wait_before_zc_scan
|
|
|
|
store_times_decrease_fast:
|
|
mov Wt_Comm_Start_L, Temp1 ; Now commutation time (~60deg) divided by 4 (~15deg nominal)
|
|
mov Wt_Adv_Start_L, Temp3 ; New commutation advance time (~15deg nominal)
|
|
mov Wt_Zc_Scan_Start_L, Temp5 ; Use this value for zero cross scan delay (7.5deg)
|
|
|
|
|
|
;**** **** **** **** **** **** **** **** **** **** **** **** ****
|
|
;
|
|
; Wait before zero cross scan routine
|
|
;
|
|
; No assumptions
|
|
;
|
|
; Waits for the zero cross scan wait time to elapse
|
|
; Also sets up timer 3 for the zero cross scan timeout time
|
|
;
|
|
;**** **** **** **** **** **** **** **** **** **** **** **** ****
|
|
wait_before_zc_scan:
|
|
jnb Flags0.T3_PENDING, ($+5)
|
|
ajmp wait_before_zc_scan
|
|
|
|
mov Startup_Zc_Timeout_Cntd, #2
|
|
setup_zc_scan_timeout:
|
|
setb Flags0.T3_PENDING
|
|
orl EIE1, #80h ; Enable timer 3 interrupts
|
|
mov A, Flags1
|
|
anl A, #((1 SHL STARTUP_PHASE)+(1 SHL INITIAL_RUN_PHASE))
|
|
jz wait_before_zc_scan_exit
|
|
|
|
mov Temp1, Comm_Period4x_L ; Set long timeout when starting
|
|
mov Temp2, Comm_Period4x_H
|
|
clr C
|
|
mov A, Temp2
|
|
rrc A
|
|
mov Temp2, A
|
|
mov A, Temp1
|
|
rrc A
|
|
mov Temp1, A
|
|
IF MCU_48MHZ == 0
|
|
clr C
|
|
mov A, Temp2
|
|
rrc A
|
|
mov Temp2, A
|
|
mov A, Temp1
|
|
rrc A
|
|
mov Temp1, A
|
|
ENDIF
|
|
jnb Flags1.STARTUP_PHASE, setup_zc_scan_timeout_startup_done
|
|
|
|
mov A, Temp2
|
|
add A, #40h ; Increase timeout somewhat to avoid false wind up
|
|
mov Temp2, A
|
|
|
|
setup_zc_scan_timeout_startup_done:
|
|
clr IE_EA
|
|
anl EIE1, #7Fh ; Disable timer 3 interrupts
|
|
mov TMR3CN0, #00h ; Timer 3 disabled and interrupt flag cleared
|
|
clr C
|
|
clr A
|
|
subb A, Temp1 ; Set timeout
|
|
mov TMR3L, A
|
|
clr A
|
|
subb A, Temp2
|
|
mov TMR3H, A
|
|
mov TMR3CN0, #04h ; Timer 3 enabled and interrupt flag cleared
|
|
setb Flags0.T3_PENDING
|
|
orl EIE1, #80h ; Enable timer 3 interrupts
|
|
setb IE_EA
|
|
|
|
wait_before_zc_scan_exit:
|
|
ret
|
|
|
|
|
|
;**** **** **** **** **** **** **** **** **** **** **** **** ****
|
|
;
|
|
; Wait for comparator to go low/high routines
|
|
;
|
|
; No assumptions
|
|
;
|
|
; Waits for the zero cross scan wait time to elapse
|
|
; Then scans for comparator going low/high
|
|
;
|
|
;**** **** **** **** **** **** **** **** **** **** **** **** ****
|
|
wait_for_comp_out_low:
|
|
setb Flags0.DEMAG_DETECTED ; Set demag detected flag as default
|
|
mov Comparator_Read_Cnt, #0 ; Reset number of comparator reads
|
|
mov Bit_Access, #00h ; Desired comparator output
|
|
jnb Flags1.DIR_CHANGE_BRAKE, ($+6)
|
|
mov Bit_Access, #40h
|
|
ajmp wait_for_comp_out_start
|
|
|
|
wait_for_comp_out_high:
|
|
setb Flags0.DEMAG_DETECTED ; Set demag detected flag as default
|
|
mov Comparator_Read_Cnt, #0 ; Reset number of comparator reads
|
|
mov Bit_Access, #40h ; Desired comparator output
|
|
jnb Flags1.DIR_CHANGE_BRAKE, ($+6)
|
|
mov Bit_Access, #00h
|
|
|
|
wait_for_comp_out_start:
|
|
; Set number of comparator readings
|
|
mov Temp1, #1 ; Number of OK readings required
|
|
mov Temp2, #1 ; Max number of readings required
|
|
jb Flags1.HIGH_RPM, comp_scale_samples ; Branch if high rpm
|
|
|
|
mov A, Flags1 ; Clear demag detected flag if start phases
|
|
anl A, #((1 SHL STARTUP_PHASE)+(1 SHL INITIAL_RUN_PHASE))
|
|
jz ($+4)
|
|
|
|
clr Flags0.DEMAG_DETECTED
|
|
|
|
mov Temp2, #20 ; Too low value (~<15) causes rough running at pwm harmonics. Too high a value (~>35) causes the RCT4215 630 to run rough on full throttle
|
|
mov A, Comm_Period4x_H ; Set number of readings higher for lower speeds
|
|
clr C
|
|
rrc A
|
|
jnz ($+3)
|
|
inc A
|
|
mov Temp1, A
|
|
clr C
|
|
subb A, #20
|
|
jc ($+4)
|
|
|
|
mov Temp1, #20
|
|
|
|
jnb Flags1.STARTUP_PHASE, comp_scale_samples
|
|
|
|
mov Temp1, #27 ; Set many samples during startup, approximately one pwm period
|
|
mov Temp2, #27
|
|
|
|
comp_scale_samples:
|
|
IF MCU_48MHZ == 1
|
|
clr C
|
|
mov A, Temp1
|
|
rlc A
|
|
mov Temp1, A
|
|
clr C
|
|
mov A, Temp2
|
|
rlc A
|
|
mov Temp2, A
|
|
ENDIF
|
|
comp_check_timeout:
|
|
jb Flags0.T3_PENDING, comp_check_timeout_not_timed_out ; Has zero cross scan timeout elapsed?
|
|
|
|
mov A, Comparator_Read_Cnt ; Check that comparator has been read
|
|
jz comp_check_timeout_not_timed_out ; If not read - branch
|
|
|
|
jnb Flags1.STARTUP_PHASE, comp_check_timeout_timeout_extended ; Extend timeout during startup
|
|
|
|
djnz Startup_Zc_Timeout_Cntd, comp_check_timeout_extend_timeout
|
|
|
|
comp_check_timeout_timeout_extended:
|
|
setb Flags0.COMP_TIMED_OUT
|
|
ajmp setup_comm_wait
|
|
|
|
comp_check_timeout_extend_timeout:
|
|
call setup_zc_scan_timeout
|
|
comp_check_timeout_not_timed_out:
|
|
inc Comparator_Read_Cnt ; Increment comparator read count
|
|
Read_Comp_Out ; Read comparator output
|
|
anl A, #40h
|
|
cjne A, Bit_Access, comp_read_wrong
|
|
ajmp comp_read_ok
|
|
|
|
comp_read_wrong:
|
|
jnb Flags1.STARTUP_PHASE, comp_read_wrong_not_startup
|
|
|
|
inc Temp1 ; Increment number of OK readings required
|
|
clr C
|
|
mov A, Temp1
|
|
subb A, Temp2 ; If above initial requirement - do not increment further
|
|
jc ($+3)
|
|
dec Temp1
|
|
|
|
ajmp comp_check_timeout ; Continue to look for good ones
|
|
|
|
comp_read_wrong_not_startup:
|
|
jb Flags0.DEMAG_DETECTED, comp_read_wrong_extend_timeout
|
|
|
|
inc Temp1 ; Increment number of OK readings required
|
|
clr C
|
|
mov A, Temp1
|
|
subb A, Temp2
|
|
jc ($+4)
|
|
ajmp wait_for_comp_out_start ; If above initial requirement - go back and restart
|
|
|
|
ajmp comp_check_timeout ; Otherwise - take another reading
|
|
|
|
comp_read_wrong_extend_timeout:
|
|
clr Flags0.DEMAG_DETECTED ; Clear demag detected flag
|
|
anl EIE1, #7Fh ; Disable timer 3 interrupts
|
|
mov TMR3CN0, #00h ; Timer 3 disabled and interrupt flag cleared
|
|
jnb Flags1.HIGH_RPM, comp_read_wrong_low_rpm ; Branch if not high rpm
|
|
|
|
mov TMR3L, #00h ; Set timeout to ~1ms
|
|
IF MCU_48MHZ == 1
|
|
mov TMR3H, #0F0h
|
|
ELSE
|
|
mov TMR3H, #0F8h
|
|
ENDIF
|
|
comp_read_wrong_timeout_set:
|
|
mov TMR3CN0, #04h ; Timer 3 enabled and interrupt flag cleared
|
|
setb Flags0.T3_PENDING
|
|
orl EIE1, #80h ; Enable timer 3 interrupts
|
|
ljmp wait_for_comp_out_start ; If comparator output is not correct - go back and restart
|
|
|
|
comp_read_wrong_low_rpm:
|
|
mov A, Comm_Period4x_H ; Set timeout to ~4x comm period 4x value
|
|
mov Temp7, #0FFh ; Default to long
|
|
IF MCU_48MHZ == 1
|
|
clr C
|
|
rlc A
|
|
jc comp_read_wrong_load_timeout
|
|
|
|
ENDIF
|
|
clr C
|
|
rlc A
|
|
jc comp_read_wrong_load_timeout
|
|
|
|
clr C
|
|
rlc A
|
|
jc comp_read_wrong_load_timeout
|
|
|
|
mov Temp7, A
|
|
|
|
comp_read_wrong_load_timeout:
|
|
clr C
|
|
clr A
|
|
subb A, Temp7
|
|
mov TMR3L, #0
|
|
mov TMR3H, A
|
|
ajmp comp_read_wrong_timeout_set
|
|
|
|
comp_read_ok:
|
|
clr C
|
|
mov A, Startup_Cnt ; Force a timeout for the first commutation
|
|
subb A, #1
|
|
jnc ($+4)
|
|
ajmp wait_for_comp_out_start
|
|
|
|
jnb Flags0.DEMAG_DETECTED, ($+5) ; Do not accept correct comparator output if it is demag
|
|
ajmp wait_for_comp_out_start
|
|
|
|
djnz Temp1, comp_read_ok_jmp ; Decrement readings counter - repeat comparator reading if not zero
|
|
ajmp ($+4)
|
|
|
|
comp_read_ok_jmp:
|
|
ajmp comp_check_timeout
|
|
|
|
clr Flags0.COMP_TIMED_OUT
|
|
|
|
|
|
;**** **** **** **** **** **** **** **** **** **** **** **** ****
|
|
;
|
|
; Setup commutation timing routine
|
|
;
|
|
; No assumptions
|
|
;
|
|
; Sets up and starts wait from commutation to zero cross
|
|
;
|
|
;**** **** **** **** **** **** **** **** **** **** **** **** ****
|
|
setup_comm_wait:
|
|
clr IE_EA
|
|
anl EIE1, #7Fh ; Disable timer 3 interrupts
|
|
mov TMR3CN0, #00h ; Timer 3 disabled and interrupt flag cleared
|
|
mov TMR3L, Wt_Comm_Start_L
|
|
mov TMR3H, Wt_Comm_Start_H
|
|
mov TMR3CN0, #04h ; Timer 3 enabled and interrupt flag cleared
|
|
; Setup next wait time
|
|
mov TMR3RLL, Wt_Adv_Start_L
|
|
mov TMR3RLH, Wt_Adv_Start_H
|
|
setb Flags0.T3_PENDING
|
|
orl EIE1, #80h ; Enable timer 3 interrupts
|
|
setb IE_EA ; Enable interrupts again
|
|
|
|
|
|
;**** **** **** **** **** **** **** **** **** **** **** **** ****
|
|
;
|
|
; Evaluate comparator integrity
|
|
;
|
|
; No assumptions
|
|
;
|
|
; Checks comparator signal behaviour versus expected behaviour
|
|
;
|
|
;**** **** **** **** **** **** **** **** **** **** **** **** ****
|
|
evaluate_comparator_integrity:
|
|
mov A, Flags1
|
|
anl A, #((1 SHL STARTUP_PHASE)+(1 SHL INITIAL_RUN_PHASE))
|
|
jz eval_comp_check_timeout
|
|
|
|
jb Flags1.INITIAL_RUN_PHASE, ($+5) ; Do not increment beyond startup phase
|
|
inc Startup_Cnt ; Increment counter
|
|
jmp eval_comp_exit
|
|
|
|
eval_comp_check_timeout:
|
|
jnb Flags0.COMP_TIMED_OUT, eval_comp_exit ; Has timeout elapsed?
|
|
jb Flags1.DIR_CHANGE_BRAKE, eval_comp_exit ; Do not exit run mode if it is braking
|
|
jb Flags0.DEMAG_DETECTED, eval_comp_exit ; Do not exit run mode if it is a demag situation
|
|
dec SP ; Routine exit without "ret" command
|
|
dec SP
|
|
ljmp run_to_wait_for_power_on_fail ; Yes - exit run mode
|
|
|
|
eval_comp_exit:
|
|
ret
|
|
|
|
|
|
;**** **** **** **** **** **** **** **** **** **** **** **** ****
|
|
;
|
|
; Wait for commutation routine
|
|
;
|
|
; No assumptions
|
|
;
|
|
; Waits from zero cross to commutation
|
|
;
|
|
;**** **** **** **** **** **** **** **** **** **** **** **** ****
|
|
wait_for_comm:
|
|
; Update demag metric
|
|
mov Temp1, #0
|
|
jnb Flags0.DEMAG_DETECTED, ($+5)
|
|
|
|
mov Temp1, #1
|
|
|
|
mov A, Demag_Detected_Metric ; Sliding average of 8, 256 when demag and 0 when not. Limited to minimum 120
|
|
mov B, #7
|
|
mul AB ; Multiply by 7
|
|
mov Temp2, A
|
|
mov A, B ; Add new value for current demag status
|
|
add A, Temp1
|
|
mov B, A
|
|
mov A, Temp2
|
|
mov C, B.0 ; Divide by 8
|
|
rrc A
|
|
mov C, B.1
|
|
rrc A
|
|
mov C, B.2
|
|
rrc A
|
|
mov Demag_Detected_Metric, A
|
|
clr C
|
|
subb A, #120 ; Limit to minimum 120
|
|
jnc ($+5)
|
|
|
|
mov Demag_Detected_Metric, #120
|
|
|
|
clr C
|
|
mov A, Demag_Detected_Metric ; Check demag metric
|
|
subb A, Demag_Pwr_Off_Thresh
|
|
jc wait_for_comm_wait ; Cut power if many consecutive demags. This will help retain sync during hard accelerations
|
|
|
|
All_pwmFETs_off
|
|
Set_Pwms_Off
|
|
|
|
wait_for_comm_wait:
|
|
jnb Flags0.T3_PENDING, ($+5)
|
|
ajmp wait_for_comm_wait
|
|
|
|
; Setup next wait time
|
|
mov TMR3RLL, Wt_Zc_Scan_Start_L
|
|
mov TMR3RLH, Wt_Zc_Scan_Start_H
|
|
setb Flags0.T3_PENDING
|
|
orl EIE1, #80h ; Enable timer 3 interrupts
|
|
ret
|
|
|
|
|
|
;**** **** **** **** **** **** **** **** **** **** **** **** ****
|
|
;
|
|
; Commutation routines
|
|
;
|
|
; No assumptions
|
|
;
|
|
; Performs commutation switching
|
|
;
|
|
;**** **** **** **** **** **** **** **** **** **** **** **** ****
|
|
; Comm phase 1 to comm phase 2
|
|
comm1comm2:
|
|
Set_RPM_Out
|
|
jb Flags3.PGM_DIR_REV, comm12_rev
|
|
|
|
clr IE_EA ; Disable all interrupts
|
|
BcomFET_off ; Turn off comfet
|
|
AcomFET_on ; Turn on comfet
|
|
Set_Pwm_C ; To reapply power after a demag cut
|
|
setb IE_EA
|
|
Set_Comp_Phase_B ; Set comparator phase
|
|
jmp comm_exit
|
|
|
|
comm12_rev:
|
|
clr IE_EA ; Disable all interrupts
|
|
BcomFET_off ; Turn off comfet
|
|
CcomFET_on ; Turn on comfet (reverse)
|
|
Set_Pwm_A ; To reapply power after a demag cut
|
|
setb IE_EA
|
|
Set_Comp_Phase_B ; Set comparator phase
|
|
jmp comm_exit
|
|
|
|
|
|
; Comm phase 2 to comm phase 3
|
|
comm2comm3:
|
|
Clear_RPM_Out
|
|
jb Flags3.PGM_DIR_REV, comm23_rev
|
|
|
|
clr IE_EA ; Disable all interrupts
|
|
CpwmFET_off ; Turn off pwmfet
|
|
Set_Pwm_B ; To reapply power after a demag cut
|
|
AcomFET_on
|
|
setb IE_EA
|
|
Set_Comp_Phase_C ; Set comparator phase
|
|
ajmp comm_exit
|
|
|
|
comm23_rev:
|
|
clr IE_EA ; Disable all interrupts
|
|
ApwmFET_off ; Turn off pwmfet (reverse)
|
|
Set_Pwm_B ; To reapply power after a demag cut
|
|
CcomFET_on
|
|
setb IE_EA
|
|
Set_Comp_Phase_A ; Set comparator phase (reverse)
|
|
ajmp comm_exit
|
|
|
|
|
|
; Comm phase 3 to comm phase 4
|
|
comm3comm4:
|
|
Set_RPM_Out
|
|
jb Flags3.PGM_DIR_REV, comm34_rev
|
|
|
|
clr IE_EA ; Disable all interrupts
|
|
AcomFET_off ; Turn off comfet
|
|
CcomFET_on ; Turn on comfet
|
|
Set_Pwm_B ; To reapply power after a demag cut
|
|
setb IE_EA
|
|
Set_Comp_Phase_A ; Set comparator phase
|
|
jmp comm_exit
|
|
|
|
comm34_rev:
|
|
clr IE_EA ; Disable all interrupts
|
|
CcomFET_off ; Turn off comfet (reverse)
|
|
AcomFET_on ; Turn on comfet (reverse)
|
|
Set_Pwm_B ; To reapply power after a demag cut
|
|
setb IE_EA
|
|
Set_Comp_Phase_C ; Set comparator phase (reverse)
|
|
jmp comm_exit
|
|
|
|
|
|
; Comm phase 4 to comm phase 5
|
|
comm4comm5:
|
|
Clear_RPM_Out
|
|
jb Flags3.PGM_DIR_REV, comm45_rev
|
|
|
|
clr IE_EA ; Disable all interrupts
|
|
BpwmFET_off ; Turn off pwmfet
|
|
Set_Pwm_A ; To reapply power after a demag cut
|
|
CcomFET_on
|
|
setb IE_EA
|
|
Set_Comp_Phase_B ; Set comparator phase
|
|
jmp comm_exit
|
|
|
|
comm45_rev:
|
|
clr IE_EA ; Disable all interrupts
|
|
BpwmFET_off ; Turn off pwmfet
|
|
Set_Pwm_C
|
|
AcomFET_on ; To reapply power after a demag cut
|
|
setb IE_EA
|
|
Set_Comp_Phase_B ; Set comparator phase
|
|
jmp comm_exit
|
|
|
|
|
|
; Comm phase 5 to comm phase 6
|
|
comm5comm6:
|
|
Set_RPM_Out
|
|
jb Flags3.PGM_DIR_REV, comm56_rev
|
|
|
|
clr IE_EA ; Disable all interrupts
|
|
CcomFET_off ; Turn off comfet
|
|
BcomFET_on ; Turn on comfet
|
|
Set_Pwm_A ; To reapply power after a demag cut
|
|
setb IE_EA
|
|
Set_Comp_Phase_C ; Set comparator phase
|
|
jmp comm_exit
|
|
|
|
comm56_rev:
|
|
clr IE_EA ; Disable all interrupts
|
|
AcomFET_off ; Turn off comfet (reverse)
|
|
BcomFET_on ; Turn on comfet
|
|
Set_Pwm_C ; To reapply power after a demag cut
|
|
setb IE_EA
|
|
Set_Comp_Phase_A ; Set comparator phase (reverse)
|
|
jmp comm_exit
|
|
|
|
|
|
; Comm phase 6 to comm phase 1
|
|
comm6comm1:
|
|
Clear_RPM_Out
|
|
jb Flags3.PGM_DIR_REV, comm61_rev
|
|
|
|
clr IE_EA ; Disable all interrupts
|
|
ApwmFET_off ; Turn off pwmfet
|
|
Set_Pwm_C
|
|
BcomFET_on ; To reapply power after a demag cut
|
|
setb IE_EA
|
|
Set_Comp_Phase_A ; Set comparator phase
|
|
jmp comm_exit
|
|
|
|
comm61_rev:
|
|
clr IE_EA ; Disable all interrupts
|
|
CpwmFET_off ; Turn off pwmfet (reverse)
|
|
Set_Pwm_A
|
|
BcomFET_on ; To reapply power after a demag cut
|
|
setb IE_EA
|
|
Set_Comp_Phase_C ; Set comparator phase (reverse)
|
|
|
|
comm_exit:
|
|
ret
|
|
|
|
|
|
;**** **** **** **** **** **** **** **** **** **** **** **** ****
|
|
;
|
|
; Beeper routines (4 different entry points)
|
|
;
|
|
; No assumptions
|
|
;
|
|
;**** **** **** **** **** **** **** **** **** **** **** **** ****
|
|
beep_f1: ; Entry point 1, load beeper frequency 1 settings
|
|
mov Temp3, #20 ; Off wait loop length
|
|
mov Temp4, #120 ; Number of beep pulses
|
|
jmp beep
|
|
|
|
beep_f2: ; Entry point 2, load beeper frequency 2 settings
|
|
mov Temp3, #16
|
|
mov Temp4, #140
|
|
jmp beep
|
|
|
|
beep_f3: ; Entry point 3, load beeper frequency 3 settings
|
|
mov Temp3, #13
|
|
mov Temp4, #180
|
|
jmp beep
|
|
|
|
beep_f4: ; Entry point 4, load beeper frequency 4 settings
|
|
mov Temp3, #11
|
|
mov Temp4, #200
|
|
jmp beep
|
|
|
|
beep: ; Beep loop start
|
|
mov A, Beep_Strength
|
|
djnz ACC, beep_start
|
|
ret
|
|
|
|
beep_start:
|
|
mov Temp2, #2
|
|
beep_onoff:
|
|
clr A
|
|
BcomFET_off ; BcomFET off
|
|
djnz ACC, $ ; Allow some time after comfet is turned off
|
|
BpwmFET_on ; BpwmFET on (in order to charge the driver of the BcomFET)
|
|
djnz ACC, $ ; Let the pwmfet be turned on a while
|
|
BpwmFET_off ; BpwmFET off again
|
|
djnz ACC, $ ; Allow some time after pwmfet is turned off
|
|
BcomFET_on ; BcomFET on
|
|
djnz ACC, $ ; Allow some time after comfet is turned on
|
|
; Turn on pwmfet
|
|
mov A, Temp2
|
|
jb ACC.0, beep_apwmfet_on
|
|
ApwmFET_on ; ApwmFET on
|
|
beep_apwmfet_on:
|
|
jnb ACC.0, beep_cpwmfet_on
|
|
CpwmFET_on ; CpwmFET on
|
|
beep_cpwmfet_on:
|
|
mov A, Beep_Strength
|
|
djnz ACC, $
|
|
; Turn off pwmfet
|
|
mov A, Temp2
|
|
jb ACC.0, beep_apwmfet_off
|
|
ApwmFET_off ; ApwmFET off
|
|
beep_apwmfet_off:
|
|
jnb ACC.0, beep_cpwmfet_off
|
|
CpwmFET_off ; CpwmFET off
|
|
beep_cpwmfet_off:
|
|
mov A, #150 ; 25us off
|
|
djnz ACC, $
|
|
djnz Temp2, beep_onoff
|
|
; Copy variable
|
|
mov A, Temp3
|
|
mov Temp1, A
|
|
beep_off: ; Fets off loop
|
|
djnz ACC, $
|
|
djnz Temp1, beep_off
|
|
djnz Temp4, beep
|
|
BcomFET_off ; BcomFET off
|
|
ret
|
|
|
|
|
|
;**** **** **** **** **** **** **** **** **** **** **** **** ****
|
|
;
|
|
; Switch power off routine
|
|
;
|
|
; No assumptions
|
|
;
|
|
; Switches all fets off
|
|
;
|
|
;**** **** **** **** **** **** **** **** **** **** **** **** ****
|
|
switch_power_off:
|
|
All_pwmFETs_Off ; Turn off all pwm fets
|
|
All_comFETs_Off ; Turn off all commutation fets
|
|
Set_Pwms_Off
|
|
ret
|
|
|
|
|
|
;**** **** **** **** **** **** **** **** **** **** **** **** ****
|
|
;
|
|
; Set default parameters
|
|
;
|
|
; No assumptions
|
|
;
|
|
; Sets default programming parameters
|
|
;
|
|
;**** **** **** **** **** **** **** **** **** **** **** **** ****
|
|
set_default_parameters:
|
|
mov Temp1, #_Pgm_Gov_P_Gain
|
|
mov @Temp1, #0FFh ; Governor P gain
|
|
inc Temp1
|
|
mov @Temp1, #0FFh ; Governor I gain
|
|
inc Temp1
|
|
mov @Temp1, #0FFh ; Governor mode
|
|
inc Temp1
|
|
mov @Temp1, #0FFh ; Low voltage limit
|
|
inc Temp1
|
|
mov @Temp1, #0FFh ; Multi gain
|
|
inc Temp1
|
|
mov @Temp1, #0FFh
|
|
inc Temp1
|
|
mov @Temp1, #DEFAULT_PGM_STARTUP_PWR
|
|
inc Temp1
|
|
mov @Temp1, #0FFh ; Pwm freq
|
|
inc Temp1
|
|
mov @Temp1, #DEFAULT_PGM_DIRECTION
|
|
|
|
mov Temp1, #Pgm_Enable_TX_Program
|
|
mov @Temp1, #DEFAULT_PGM_ENABLE_TX_PROGRAM
|
|
inc Temp1
|
|
mov @Temp1, #0FFh ; Main rearm start
|
|
inc Temp1
|
|
mov @Temp1, #0FFh ; Governor setup target
|
|
inc Temp1
|
|
mov @Temp1, #0FFh ; Startup rpm
|
|
inc Temp1
|
|
mov @Temp1, #0FFh ; Startup accel
|
|
inc Temp1
|
|
mov @Temp1, #0FFh ; Voltage comp
|
|
inc Temp1
|
|
mov @Temp1, #DEFAULT_PGM_COMM_TIMING
|
|
inc Temp1
|
|
mov @Temp1, #0FFh ; Damping force
|
|
inc Temp1
|
|
mov @Temp1, #0FFh ; Governor range
|
|
inc Temp1
|
|
mov @Temp1, #0FFh ; Startup method
|
|
inc Temp1
|
|
mov @Temp1, #DEFAULT_PGM_MIN_THROTTLE
|
|
inc Temp1
|
|
mov @Temp1, #DEFAULT_PGM_MAX_THROTTLE
|
|
inc Temp1
|
|
mov @Temp1, #DEFAULT_PGM_BEEP_STRENGTH
|
|
inc Temp1
|
|
mov @Temp1, #DEFAULT_PGM_BEACON_STRENGTH
|
|
inc Temp1
|
|
mov @Temp1, #DEFAULT_PGM_BEACON_DELAY
|
|
inc Temp1
|
|
mov @Temp1, #0FFh ; Throttle rate
|
|
inc Temp1
|
|
mov @Temp1, #DEFAULT_PGM_DEMAG_COMP
|
|
inc Temp1
|
|
mov @Temp1, #0FFh ; Bec voltage high
|
|
inc Temp1
|
|
mov @Temp1, #DEFAULT_PGM_CENTER_THROTTLE
|
|
inc Temp1
|
|
mov @Temp1, #0FFh
|
|
inc Temp1
|
|
mov @Temp1, #DEFAULT_PGM_ENABLE_TEMP_PROT
|
|
inc Temp1
|
|
mov @Temp1, #DEFAULT_PGM_ENABLE_POWER_PROT
|
|
inc Temp1
|
|
mov @Temp1, #0FFh ; Enable pwm input
|
|
inc Temp1
|
|
mov @Temp1, #0FFh ; Pwm dither
|
|
inc Temp1
|
|
mov @Temp1, #DEFAULT_PGM_BRAKE_ON_STOP
|
|
inc Temp1
|
|
mov @Temp1, #DEFAULT_PGM_LED_CONTROL
|
|
ret
|
|
|
|
|
|
;**** **** **** **** **** **** **** **** **** **** **** **** ****
|
|
;
|
|
; Scale throttle cal
|
|
;
|
|
; No assumptions
|
|
;
|
|
; Scales a throttle cal value
|
|
; Input is ACC, output is Temp2/Temp1
|
|
;
|
|
;**** **** **** **** **** **** **** **** **** **** **** **** ****
|
|
scale_throttle_cal:
|
|
mov Temp3, A
|
|
mov B, #0Ch ; Calculate "3%" (for going from 1000us to numerical 1024)
|
|
mul AB
|
|
mov Temp4, B
|
|
mov A, Temp3
|
|
clr C ; Shift to 9 bits
|
|
rlc A
|
|
mov Temp1, A
|
|
mov A, #1
|
|
rlc A
|
|
mov Temp2, A
|
|
mov A, Temp1 ; Shift to 10 bits
|
|
clr C
|
|
rlc A
|
|
mov Temp1, A
|
|
mov A, Temp2
|
|
rlc A
|
|
mov Temp2, A
|
|
mov A, Temp1 ; Add "3%"
|
|
clr C
|
|
add A, Temp4
|
|
mov Temp1, A
|
|
mov A, Temp2
|
|
addc A, #0
|
|
mov Temp2, A
|
|
IF MCU_48MHZ == 1
|
|
mov A, Temp1 ; Shift to 11 bits
|
|
clr C
|
|
rlc A
|
|
mov Temp1, A
|
|
mov A, Temp2
|
|
rlc A
|
|
mov Temp2, A
|
|
ENDIF
|
|
ret
|
|
|
|
|
|
;**** **** **** **** **** **** **** **** **** **** **** **** ****
|
|
;
|
|
; Decode settings
|
|
;
|
|
; No assumptions
|
|
;
|
|
; Decodes various settings
|
|
;
|
|
;**** **** **** **** **** **** **** **** **** **** **** **** ****
|
|
decode_settings:
|
|
; Load programmed direction
|
|
mov Temp1, #Pgm_Direction
|
|
mov A, @Temp1
|
|
clr C
|
|
subb A, #3
|
|
setb Flags3.PGM_BIDIR
|
|
jnc ($+4)
|
|
|
|
clr Flags3.PGM_BIDIR
|
|
|
|
clr Flags3.PGM_DIR_REV
|
|
mov A, @Temp1
|
|
jnb ACC.1, ($+5)
|
|
setb Flags3.PGM_DIR_REV
|
|
mov C, Flags3.PGM_DIR_REV
|
|
mov Flags3.PGM_BIDIR_REV, C
|
|
; Decode startup power
|
|
mov Temp1, #Pgm_Startup_Pwr
|
|
mov A, @Temp1
|
|
dec A
|
|
mov DPTR, #STARTUP_POWER_TABLE
|
|
movc A, @A+DPTR
|
|
mov Temp1, #Pgm_Startup_Pwr_Decoded
|
|
mov @Temp1, A
|
|
; Decode low rpm power slope
|
|
mov Temp1, #Pgm_Startup_Pwr
|
|
mov A, @Temp1
|
|
mov Low_Rpm_Pwr_Slope, A
|
|
clr C
|
|
subb A, #2
|
|
jnc ($+5)
|
|
mov Low_Rpm_Pwr_Slope, #2
|
|
; Decode demag compensation
|
|
mov Temp1, #Pgm_Demag_Comp
|
|
mov A, @Temp1
|
|
mov Demag_Pwr_Off_Thresh, #255 ; Set default
|
|
|
|
cjne A, #2, decode_demag_high
|
|
|
|
mov Demag_Pwr_Off_Thresh, #160 ; Settings for demag comp low
|
|
|
|
decode_demag_high:
|
|
cjne A, #3, decode_demag_done
|
|
|
|
mov Demag_Pwr_Off_Thresh, #130 ; Settings for demag comp high
|
|
|
|
decode_demag_done:
|
|
; Decode temperature protection limit
|
|
mov Temp1, #Pgm_Enable_Temp_Prot
|
|
mov A, @Temp1
|
|
mov Temp1, A
|
|
jz decode_temp_done
|
|
|
|
mov A, #(TEMP_LIMIT-TEMP_LIMIT_STEP)
|
|
decode_temp_step:
|
|
add A, #TEMP_LIMIT_STEP
|
|
djnz Temp1, decode_temp_step
|
|
|
|
decode_temp_done:
|
|
mov Temp_Prot_Limit, A
|
|
; Decode throttle cal
|
|
mov Temp1, #Pgm_Min_Throttle ; Throttle cal is in 4us units
|
|
mov A, @Temp1
|
|
call scale_throttle_cal
|
|
mov Min_Throttle_L, Temp1
|
|
mov Min_Throttle_H, Temp2
|
|
mov Temp1, #Pgm_Center_Throttle ; Throttle cal is in 4us units
|
|
mov A, @Temp1
|
|
call scale_throttle_cal
|
|
mov Center_Throttle_L, Temp1
|
|
mov Center_Throttle_H, Temp2
|
|
mov Temp1, #Pgm_Max_Throttle ; Throttle cal is in 4us units
|
|
mov A, @Temp1
|
|
call scale_throttle_cal
|
|
mov Max_Throttle_L, Temp1
|
|
mov Max_Throttle_H, Temp2
|
|
call switch_power_off
|
|
ret
|
|
|
|
|
|
;**** **** **** **** **** **** **** **** **** **** **** **** ****
|
|
;
|
|
; Find throttle gains
|
|
;
|
|
; No assumptions
|
|
;
|
|
; Finds throttle gains for both directions in bidirectional mode
|
|
;
|
|
;**** **** **** **** **** **** **** **** **** **** **** **** ****
|
|
find_throttle_gains:
|
|
; Check if full range is chosen
|
|
jnb Flags2.RCP_FULL_RANGE, find_throttle_gains_normal
|
|
|
|
mov Temp3, #0 ; Min throttle
|
|
mov Temp4, #0
|
|
mov Temp5, #255 ; Max throttle
|
|
mov Temp6, #0
|
|
mov Temp7, #0 ; Deadband
|
|
call find_throttle_gain
|
|
mov Throttle_Gain_M, Temp4
|
|
mov Throttle_Gain, Temp3
|
|
ret
|
|
|
|
find_throttle_gains_normal:
|
|
; Check if bidirectional operation
|
|
jnb Flags3.PGM_BIDIR, find_throttle_gains_bidir_done
|
|
|
|
mov Temp1, #Pgm_Min_Throttle
|
|
mov A, @Temp1
|
|
mov Temp3, A
|
|
mov Temp4, #0
|
|
mov Temp1, #Pgm_Center_Throttle
|
|
mov A, @Temp1
|
|
mov Temp5, A
|
|
mov Temp6, #0
|
|
clr C
|
|
mov A, Temp3 ; Scale gains in bidirectional
|
|
rlc A
|
|
mov Temp3, A
|
|
mov A, Temp4
|
|
rlc A
|
|
mov Temp4, A
|
|
clr C
|
|
mov A, Temp5
|
|
rlc A
|
|
mov Temp5, A
|
|
mov A, Temp6
|
|
rlc A
|
|
mov Temp6, A
|
|
mov Temp7, #10 ; Compensate for deadband in bidirectional
|
|
call find_throttle_gain
|
|
mov Throttle_Gain_BD_Rev_M, Temp4
|
|
mov Throttle_Gain_BD_Rev, Temp3
|
|
|
|
find_throttle_gains_bidir_done:
|
|
mov Temp1, #Pgm_Min_Throttle
|
|
jnb Flags3.PGM_BIDIR, ($+5)
|
|
|
|
mov Temp1, #Pgm_Center_Throttle
|
|
|
|
mov A, @Temp1
|
|
mov Temp3, A
|
|
mov Temp4, #0
|
|
mov Temp1, #Pgm_Max_Throttle
|
|
mov A, @Temp1
|
|
mov Temp5, A
|
|
mov Temp6, #0
|
|
mov Temp7, #0 ; No deadband
|
|
jnb Flags3.PGM_BIDIR, find_throttle_gain_fwd
|
|
|
|
clr C
|
|
mov A, Temp3 ; Scale gains in bidirectional
|
|
rlc A
|
|
mov Temp3, A
|
|
mov A, Temp4
|
|
rlc A
|
|
mov Temp4, A
|
|
clr C
|
|
mov A, Temp5
|
|
rlc A
|
|
mov Temp5, A
|
|
mov A, Temp6
|
|
rlc A
|
|
mov Temp6, A
|
|
mov Temp7, #10 ; Compensate for deadband in bidirectional
|
|
|
|
find_throttle_gain_fwd:
|
|
call find_throttle_gain
|
|
mov Throttle_Gain_M, Temp4
|
|
mov Throttle_Gain, Temp3
|
|
ret
|
|
|
|
|
|
;**** **** **** **** **** **** **** **** **** **** **** **** ****
|
|
;
|
|
; Find throttle gain
|
|
;
|
|
; The difference between max and min throttle must be more than 140us (a Pgm_xxx_Throttle difference of 35)
|
|
; Temp4/3 holds min throttle, Temp6/5 holds max throttle, Temp7 holds deadband, Temp4/Temp3 gives resulting gain
|
|
;
|
|
; Finds throttle gain from throttle calibration values
|
|
;
|
|
;**** **** **** **** **** **** **** **** **** **** **** **** ****
|
|
find_throttle_gain:
|
|
; Subtract deadband from max
|
|
clr C
|
|
mov A, Temp5
|
|
subb A, Temp7
|
|
mov Temp5, A
|
|
mov A, Temp6
|
|
subb A, #0
|
|
mov Temp6, A
|
|
; Calculate difference
|
|
clr C
|
|
mov A, Temp5
|
|
subb A, Temp3
|
|
mov Temp5, A
|
|
mov A, Temp6
|
|
subb A, Temp4
|
|
mov Temp6, A
|
|
; Check that difference is minimum 35
|
|
clr C
|
|
mov A, Temp5
|
|
subb A, #35
|
|
mov A, Temp6
|
|
subb A, #0
|
|
jnc ($+6)
|
|
|
|
mov Temp5, #35
|
|
mov Temp6, #0
|
|
|
|
; Check that difference is maximum 511
|
|
clr C
|
|
mov A, Temp5
|
|
subb A, #255
|
|
mov A, Temp6
|
|
subb A, #1
|
|
jc ($+6)
|
|
|
|
mov Temp5, #255
|
|
mov Temp6, #1
|
|
|
|
; Find gain
|
|
mov Temp4, #0FFh
|
|
find_throttle_gain_loop:
|
|
inc Temp4
|
|
mov Temp3, #0
|
|
test_throttle_gain:
|
|
inc Temp3
|
|
mov A, Temp3
|
|
jnz test_throttle_gain_mult
|
|
|
|
clr C
|
|
mov A, Temp5 ; Set multiplier x2 and range /2
|
|
rlc A
|
|
mov Temp5, A
|
|
mov A, Temp6
|
|
rlc A
|
|
mov Temp6, A
|
|
ajmp find_throttle_gain_loop
|
|
|
|
test_throttle_gain_mult:
|
|
mov A, Temp5 ; A has difference, B has gain
|
|
mov B, Temp3
|
|
mul AB
|
|
mov Temp7, B
|
|
mov A, Temp6
|
|
mov B, Temp3
|
|
mul AB
|
|
add A, Temp7
|
|
subb A, #124
|
|
jc test_throttle_gain
|
|
|
|
mov A, Temp3
|
|
cpl A
|
|
jz find_throttle_gain_loop
|
|
|
|
ret
|
|
|
|
|
|
;**** **** **** **** **** **** **** **** **** **** **** **** ****
|
|
;
|
|
; Average throttle
|
|
;
|
|
; Outputs result in Temp8
|
|
;
|
|
; Averages throttle calibration readings
|
|
;
|
|
;**** **** **** **** **** **** **** **** **** **** **** **** ****
|
|
average_throttle:
|
|
setb Flags2.RCP_FULL_RANGE ; Set range to 1000-2020us
|
|
call find_throttle_gains ; Set throttle gains
|
|
call wait30ms
|
|
call wait30ms
|
|
mov Temp3, #0
|
|
mov Temp4, #0
|
|
mov Temp5, #16 ; Average 16 measurments
|
|
average_throttle_meas:
|
|
call wait3ms ; Wait for new RC pulse value
|
|
mov A, New_Rcp ; Get new RC pulse value
|
|
add A, Temp3
|
|
mov Temp3, A
|
|
mov A, #0
|
|
addc A, Temp4
|
|
mov Temp4, A
|
|
djnz Temp5, average_throttle_meas
|
|
|
|
mov Temp5, #4 ; Shift 4 times
|
|
average_throttle_div:
|
|
clr C
|
|
mov A, Temp4 ; Shift right
|
|
rrc A
|
|
mov Temp4, A
|
|
mov A, Temp3
|
|
rrc A
|
|
mov Temp3, A
|
|
djnz Temp5, average_throttle_div
|
|
|
|
mov Temp8, A ; Copy to Temp8
|
|
mov A, Temp4
|
|
jz ($+4)
|
|
|
|
mov Temp8, #0FFh
|
|
|
|
clr Flags2.RCP_FULL_RANGE
|
|
call find_throttle_gains ; Set throttle gains
|
|
ret
|
|
|
|
|
|
;**** **** **** **** **** **** **** **** **** **** **** **** ****
|
|
;
|
|
; LED control
|
|
;
|
|
; No assumptions
|
|
;
|
|
; Controls LEDs
|
|
;
|
|
;**** **** **** **** **** **** **** **** **** **** **** **** ****
|
|
led_control:
|
|
mov Temp1, #Pgm_LED_Control
|
|
mov A, @Temp1
|
|
mov Temp2, A
|
|
anl A, #03h
|
|
Set_LED_0
|
|
jnz led_0_done
|
|
Clear_LED_0
|
|
led_0_done:
|
|
mov A, Temp2
|
|
anl A, #0Ch
|
|
Set_LED_1
|
|
jnz led_1_done
|
|
Clear_LED_1
|
|
led_1_done:
|
|
mov A, Temp2
|
|
anl A, #030h
|
|
Set_LED_2
|
|
jnz led_2_done
|
|
Clear_LED_2
|
|
led_2_done:
|
|
mov A, Temp2
|
|
anl A, #0C0h
|
|
Set_LED_3
|
|
jnz led_3_done
|
|
Clear_LED_3
|
|
led_3_done:
|
|
ret
|
|
|
|
|
|
|
|
;**** **** **** **** **** **** **** **** **** **** **** **** ****
|
|
;**** **** **** **** **** **** **** **** **** **** **** **** ****
|
|
;**** **** **** **** **** **** **** **** **** **** **** **** ****
|
|
;
|
|
; Main program start
|
|
;
|
|
;**** **** **** **** **** **** **** **** **** **** **** **** ****
|
|
;**** **** **** **** **** **** **** **** **** **** **** **** ****
|
|
;**** **** **** **** **** **** **** **** **** **** **** **** ****
|
|
|
|
pgm_start:
|
|
; Initialize flash keys to invalid values
|
|
mov Flash_Key_1, #0
|
|
mov Flash_Key_2, #0
|
|
; Disable the WDT.
|
|
mov WDTCN, #0DEh ; Disable watchdog
|
|
mov WDTCN, #0ADh
|
|
; Initialize stack
|
|
mov SP, #0c0h ; Stack = 64 upper bytes of RAM
|
|
; Initialize VDD monitor
|
|
orl VDM0CN, #080h ; Enable the VDD monitor
|
|
mov RSTSRC, #06h ; Set missing clock and VDD monitor as a reset source if not 1S capable
|
|
; Set clock frequency
|
|
mov CLKSEL, #00h ; Set clock divider to 1
|
|
; Switch power off
|
|
call switch_power_off
|
|
; Ports initialization
|
|
mov P0, #P0_INIT
|
|
mov P0MDIN, #P0_DIGITAL
|
|
mov P0MDOUT, #P0_PUSHPULL
|
|
mov P0, #P0_INIT
|
|
mov P0SKIP, #P0_SKIP
|
|
mov P1, #P1_INIT
|
|
mov P1MDIN, #P1_DIGITAL
|
|
mov P1MDOUT, #P1_PUSHPULL
|
|
mov P1, #P1_INIT
|
|
mov P1SKIP, #P1_SKIP
|
|
mov P2MDOUT, #P2_PUSHPULL
|
|
; Initialize the XBAR and related functionality
|
|
Initialize_Xbar
|
|
; Switch power off again, after initializing ports
|
|
call switch_power_off
|
|
; Clear RAM
|
|
clr A ; Clear accumulator
|
|
mov Temp1, A ; Clear Temp1
|
|
clear_ram:
|
|
mov @Temp1, A ; Clear RAM
|
|
djnz Temp1, clear_ram ; Is A not zero? - jump
|
|
; Set default programmed parameters
|
|
call set_default_parameters
|
|
; Read all programmed parameters
|
|
call read_all_eeprom_parameters
|
|
; Set beep strength
|
|
mov Temp1, #Pgm_Beep_Strength
|
|
mov Beep_Strength, @Temp1
|
|
; Set initial arm variable
|
|
mov Initial_Arm, #1
|
|
; Initializing beep
|
|
clr IE_EA ; Disable interrupts explicitly
|
|
call wait200ms
|
|
call beep_f1
|
|
call wait30ms
|
|
call beep_f2
|
|
call wait30ms
|
|
call beep_f3
|
|
call wait30ms
|
|
call led_control
|
|
|
|
|
|
;**** **** **** **** **** **** **** **** **** **** **** **** ****
|
|
;
|
|
; No signal entry point
|
|
;
|
|
;**** **** **** **** **** **** **** **** **** **** **** **** ****
|
|
init_no_signal:
|
|
; Disable interrupts explicitly
|
|
clr IE_EA
|
|
; Initialize flash keys to invalid values
|
|
mov Flash_Key_1, #0
|
|
mov Flash_Key_2, #0
|
|
; Check if input signal is high for more than 15ms
|
|
mov Temp1, #250
|
|
input_high_check_1:
|
|
mov Temp2, #250
|
|
input_high_check_2:
|
|
jnb RTX_PORT.RTX_PIN, bootloader_done ; Look for low
|
|
djnz Temp2, input_high_check_2
|
|
djnz Temp1, input_high_check_1
|
|
|
|
ljmp 1C00h ; Jump to bootloader
|
|
|
|
bootloader_done:
|
|
; Decode settings
|
|
call decode_settings
|
|
; Find throttle gain from stored min and max settings
|
|
call find_throttle_gains
|
|
; Set beep strength
|
|
mov Temp1, #Pgm_Beep_Strength
|
|
mov Beep_Strength, @Temp1
|
|
; Switch power off
|
|
call switch_power_off
|
|
; Set clock frequency
|
|
IF MCU_48MHZ == 1
|
|
Set_MCU_Clk_24MHz
|
|
ENDIF
|
|
; Setup timers for pwm input
|
|
mov IT01CF, #RTX_PIN ; Route RCP input to INT0
|
|
mov TCON, #11h ; Timer 0 run and INT0 edge triggered
|
|
mov CKCON0, #04h ; Timer 0 clock is system clock
|
|
mov TMOD, #09h ; Timer 0 set to 16bits and gated by INT0
|
|
mov TMR2CN0, #04h ; Timer 2 enabled
|
|
mov TMR3CN0, #04h ; Timer 3 enabled
|
|
Initialize_PCA ; Initialize PCA
|
|
Set_Pwm_Polarity ; Set pwm polarity
|
|
Enable_Power_Pwm_Module ; Enable power pwm module
|
|
Enable_Damp_Pwm_Module ; Enable damping pwm module
|
|
; Enable interrupts
|
|
IF MCU_48MHZ == 0
|
|
mov IE, #21h ; Enable timer 2 interrupts and INT0 interrupts
|
|
ELSE
|
|
mov IE, #23h ; Enable timer 0, timer 2 interrupts and INT0 interrupts
|
|
ENDIF
|
|
mov EIE1, #90h ; Enable timer 3 and PCA0 interrupts
|
|
mov IP, #01h ; High priority to INT0 interrupts
|
|
; Initialize comparator
|
|
Initialize_Comparator ; Initialize comparator
|
|
; Initialize ADC
|
|
Initialize_Adc ; Initialize ADC operation
|
|
call wait1ms
|
|
setb IE_EA ; Enable all interrupts
|
|
; Reset stall count
|
|
mov Stall_Cnt, #0
|
|
; Initialize RC pulse
|
|
clr Flags2.RCP_UPDATED ; Clear updated flag
|
|
call wait200ms
|
|
; Clear all shot flags
|
|
clr Flags2.RCP_ONESHOT125 ; Clear OneShot125 flag
|
|
clr Flags2.RCP_ONESHOT42 ; Clear OneShot42 flag
|
|
clr Flags2.RCP_MULTISHOT ; Clear Multishot flag
|
|
clr Flags2.RCP_DSHOT ; Clear DShot flag
|
|
mov Dshot_Cmd, #0 ; Clear Dshot command
|
|
mov Dshot_Cmd_Cnt, #0 ; Clear Dshot command count
|
|
; Test whether signal is regular pwm
|
|
mov Rcp_Outside_Range_Cnt, #0 ; Reset out of range counter
|
|
call wait100ms ; Wait for new RC pulse
|
|
clr C
|
|
mov A, Rcp_Outside_Range_Cnt ; Check how many pulses were outside normal range ("900-2235us")
|
|
subb A, #10
|
|
jnc ($+4)
|
|
ajmp validate_rcp_start
|
|
|
|
; Test whether signal is OneShot125
|
|
setb Flags2.RCP_ONESHOT125 ; Set OneShot125 flag
|
|
mov Rcp_Outside_Range_Cnt, #0 ; Reset out of range counter
|
|
call wait100ms ; Wait for new RC pulse
|
|
clr C
|
|
mov A, Rcp_Outside_Range_Cnt ; Check how many pulses were outside normal range ("900-2235us")
|
|
subb A, #10
|
|
jnc ($+4)
|
|
ajmp validate_rcp_start
|
|
|
|
; Test whether signal is OneShot42
|
|
clr Flags2.RCP_ONESHOT125
|
|
setb Flags2.RCP_ONESHOT42 ; Set OneShot42 flag
|
|
mov Rcp_Outside_Range_Cnt, #0 ; Reset out of range counter
|
|
call wait100ms ; Wait for new RC pulse
|
|
clr C
|
|
mov A, Rcp_Outside_Range_Cnt ; Check how many pulses were outside normal range ("900-2235us")
|
|
subb A, #10
|
|
jnc ($+4)
|
|
ajmp validate_rcp_start
|
|
|
|
; Setup timers for DShot
|
|
mov IT01CF, #(80h+(RTX_PIN SHL 4)+(RTX_PIN)) ; Route RCP input to INT0/1, with INT1 inverted
|
|
mov TCON, #51h ; Timer 0/1 run and INT0 edge triggered
|
|
mov CKCON0, #01h ; Timer 0/1 clock is system clock divided by 4 (for DShot150)
|
|
mov TMOD, #0AAh ; Timer 0/1 set to 8bits auto reload and gated by INT0
|
|
mov TH0, #0 ; Auto reload value zero
|
|
mov TH1, #0
|
|
; Setup interrupts for DShot
|
|
clr IE_ET0 ; Disable timer 0 interrupts
|
|
setb IE_ET1 ; Enable timer 1 interrupts
|
|
setb IE_EX1 ; Enable int1 interrupts
|
|
; Setup variables for DSshot150
|
|
IF MCU_48MHZ == 1
|
|
mov DShot_Timer_Preset, #128 ; Load DShot sync timer preset (for DShot150)
|
|
ELSE
|
|
mov DShot_Timer_Preset, #192
|
|
ENDIF
|
|
mov DShot_Pwm_Thr, #20 ; Load DShot qualification pwm threshold (for DShot150)
|
|
mov DShot_Frame_Length_Thr, #80 ; Load DShot frame length criteria
|
|
; Test whether signal is DShot150
|
|
clr Flags2.RCP_ONESHOT42
|
|
setb Flags2.RCP_DSHOT
|
|
mov Rcp_Outside_Range_Cnt, #10 ; Set out of range counter
|
|
call wait100ms ; Wait for new RC pulse
|
|
mov DShot_Pwm_Thr, #16 ; Load DShot regular pwm threshold
|
|
clr C
|
|
mov A, Rcp_Outside_Range_Cnt ; Check if pulses were accepted
|
|
subb A, #10
|
|
mov Dshot_Cmd, #0
|
|
mov Dshot_Cmd_Cnt, #0
|
|
jc validate_rcp_start
|
|
|
|
; Setup variables for DShot300
|
|
mov CKCON0, #0Ch ; Timer 0/1 clock is system clock (for DShot300)
|
|
IF MCU_48MHZ == 1
|
|
mov DShot_Timer_Preset, #0 ; Load DShot sync timer preset (for DShot300)
|
|
ELSE
|
|
mov DShot_Timer_Preset, #128
|
|
ENDIF
|
|
mov DShot_Pwm_Thr, #40 ; Load DShot qualification pwm threshold (for DShot300)
|
|
mov DShot_Frame_Length_Thr, #40 ; Load DShot frame length criteria
|
|
; Test whether signal is DShot300
|
|
mov Rcp_Outside_Range_Cnt, #10 ; Set out of range counter
|
|
call wait100ms ; Wait for new RC pulse
|
|
mov DShot_Pwm_Thr, #32 ; Load DShot regular pwm threshold
|
|
clr C
|
|
mov A, Rcp_Outside_Range_Cnt ; Check if pulses were accepted
|
|
subb A, #10
|
|
mov Dshot_Cmd, #0
|
|
mov Dshot_Cmd_Cnt, #0
|
|
jc validate_rcp_start
|
|
|
|
; Setup variables for DShot600
|
|
mov CKCON0, #0Ch ; Timer 0/1 clock is system clock (for DShot600)
|
|
IF MCU_48MHZ == 1
|
|
mov DShot_Timer_Preset, #128 ; Load DShot sync timer preset (for DShot600)
|
|
ELSE
|
|
mov DShot_Timer_Preset, #192
|
|
ENDIF
|
|
mov DShot_Pwm_Thr, #20 ; Load DShot qualification pwm threshold (for DShot600)
|
|
mov DShot_Frame_Length_Thr, #20 ; Load DShot frame length criteria
|
|
; Test whether signal is DShot600
|
|
mov Rcp_Outside_Range_Cnt, #10 ; Set out of range counter
|
|
call wait100ms ; Wait for new RC pulse
|
|
mov DShot_Pwm_Thr, #16 ; Load DShot regular pwm threshold
|
|
clr C
|
|
mov A, Rcp_Outside_Range_Cnt ; Check if pulses were accepted
|
|
subb A, #10
|
|
mov Dshot_Cmd, #0
|
|
mov Dshot_Cmd_Cnt, #0
|
|
jc validate_rcp_start
|
|
|
|
; Setup timers for Multishot
|
|
mov IT01CF, #RTX_PIN ; Route RCP input to INT0
|
|
mov TCON, #11h ; Timer 0 run and INT0 edge triggered
|
|
mov CKCON0, #04h ; Timer 0 clock is system clock
|
|
mov TMOD, #09h ; Timer 0 set to 16bits and gated by INT0
|
|
; Setup interrupts for Multishot
|
|
setb IE_ET0 ; Enable timer 0 interrupts
|
|
clr IE_ET1 ; Disable timer 1 interrupts
|
|
clr IE_EX1 ; Disable int1 interrupts
|
|
; Test whether signal is Multishot
|
|
clr Flags2.RCP_DSHOT
|
|
setb Flags2.RCP_MULTISHOT ; Set Multishot flag
|
|
mov Rcp_Outside_Range_Cnt, #0 ; Reset out of range counter
|
|
call wait100ms ; Wait for new RC pulse
|
|
clr C
|
|
mov A, Rcp_Outside_Range_Cnt ; Check how many pulses were outside normal range ("900-2235us")
|
|
subb A, #10
|
|
jc validate_rcp_start
|
|
|
|
ajmp init_no_signal
|
|
|
|
validate_rcp_start:
|
|
; Validate RC pulse
|
|
call wait3ms ; Wait for new RC pulse
|
|
jb Flags2.RCP_UPDATED, ($+6) ; Is there an updated RC pulse available - proceed
|
|
ljmp init_no_signal ; Go back to detect input signal
|
|
|
|
; Beep arm sequence start signal
|
|
clr IE_EA ; Disable all interrupts
|
|
call beep_f1 ; Signal that RC pulse is ready
|
|
call beep_f1
|
|
call beep_f1
|
|
setb IE_EA ; Enable all interrupts
|
|
call wait200ms
|
|
|
|
; Arming sequence start
|
|
arming_start:
|
|
jb Flags2.RCP_DSHOT, ($+6) ; Disable tx programming for DShot
|
|
jnb Flags3.PGM_BIDIR, ($+6)
|
|
|
|
ljmp program_by_tx_checked ; Disable tx programming if bidirectional operation
|
|
|
|
call wait3ms
|
|
mov Temp1, #Pgm_Enable_TX_Program; Start programming mode entry if enabled
|
|
mov A, @Temp1
|
|
clr C
|
|
subb A, #1 ; Is TX programming enabled?
|
|
jnc arming_initial_arm_check ; Yes - proceed
|
|
|
|
jmp program_by_tx_checked ; No - branch
|
|
|
|
arming_initial_arm_check:
|
|
mov A, Initial_Arm ; Yes - check if it is initial arm sequence
|
|
clr C
|
|
subb A, #1 ; Is it the initial arm sequence?
|
|
jnc arming_check ; Yes - proceed
|
|
|
|
jmp program_by_tx_checked ; No - branch
|
|
|
|
arming_check:
|
|
; Initialize flash keys to valid values
|
|
mov Flash_Key_1, #0A5h
|
|
mov Flash_Key_2, #0F1h
|
|
; Throttle calibration and tx program entry
|
|
mov Temp8, #2 ; Set 1 seconds wait time
|
|
throttle_high_cal:
|
|
setb Flags2.RCP_FULL_RANGE ; Set range to 1000-2020us
|
|
call find_throttle_gains ; Set throttle gains
|
|
call wait100ms ; Wait for new throttle value
|
|
clr IE_EA ; Disable interrupts (freeze New_Rcp value)
|
|
clr Flags2.RCP_FULL_RANGE ; Set programmed range
|
|
call find_throttle_gains ; Set throttle gains
|
|
clr C
|
|
mov A, New_Rcp ; Load new RC pulse value
|
|
subb A, #(255/2) ; Is RC pulse above midstick?
|
|
setb IE_EA ; Enable interrupts
|
|
jc program_by_tx_checked ; No - branch
|
|
|
|
call wait1ms
|
|
clr IE_EA ; Disable all interrupts
|
|
call beep_f4
|
|
setb IE_EA ; Enable all interrupts
|
|
djnz Temp8, throttle_high_cal ; Continue to wait
|
|
|
|
call average_throttle
|
|
clr C
|
|
mov A, Temp8
|
|
mov Temp1, #Pgm_Max_Throttle ; Store
|
|
mov @Temp1, A
|
|
call wait200ms
|
|
call success_beep
|
|
|
|
throttle_low_cal_start:
|
|
mov Temp8, #10 ; Set 3 seconds wait time
|
|
throttle_low_cal:
|
|
setb Flags2.RCP_FULL_RANGE ; Set range to 1000-2020us
|
|
call find_throttle_gains ; Set throttle gains
|
|
call wait100ms
|
|
clr IE_EA ; Disable interrupts (freeze New_Rcp value)
|
|
clr Flags2.RCP_FULL_RANGE ; Set programmed range
|
|
call find_throttle_gains ; Set throttle gains
|
|
clr C
|
|
mov A, New_Rcp ; Load new RC pulse value
|
|
subb A, #(255/2) ; Below midstick?
|
|
setb IE_EA ; Enable interrupts
|
|
jnc throttle_low_cal_start ; No - start over
|
|
|
|
call wait1ms
|
|
clr IE_EA ; Disable all interrupts
|
|
call beep_f1
|
|
call wait10ms
|
|
call beep_f1
|
|
setb IE_EA ; Enable all interrupts
|
|
djnz Temp8, throttle_low_cal ; Continue to wait
|
|
|
|
call average_throttle
|
|
mov A, Temp8
|
|
add A, #3 ; Add about 1%
|
|
mov Temp1, #Pgm_Min_Throttle ; Store
|
|
mov @Temp1, A
|
|
mov Temp1, A ; Min throttle in Temp1
|
|
mov Temp2, #Pgm_Max_Throttle
|
|
mov A, @Temp2
|
|
clr C
|
|
subb A, #35 ; Subtract 35 (140us) from max throttle
|
|
jc program_by_tx_entry_limit
|
|
subb A, Temp1 ; Subtract min from max
|
|
jnc program_by_tx_entry_store
|
|
|
|
program_by_tx_entry_limit:
|
|
mov A, Temp1 ; Load min
|
|
add A, #35 ; Make max 140us higher than min
|
|
mov Temp1, #Pgm_Max_Throttle ; Store new max
|
|
mov @Temp1, A
|
|
|
|
program_by_tx_entry_store:
|
|
call wait200ms
|
|
call erase_and_store_all_in_eeprom
|
|
call success_beep_inverted
|
|
|
|
program_by_tx_entry_wait:
|
|
call wait100ms
|
|
call find_throttle_gains ; Set throttle gains
|
|
ljmp init_no_signal ; Go back
|
|
|
|
program_by_tx_checked:
|
|
; Initialize flash keys to invalid values
|
|
mov Flash_Key_1, #0
|
|
mov Flash_Key_2, #0
|
|
call wait100ms ; Wait for new throttle value
|
|
clr C
|
|
mov A, New_Rcp ; Load new RC pulse value
|
|
subb A, #1 ; Below stop?
|
|
jc arm_end_beep ; Yes - proceed
|
|
|
|
jmp arming_start ; No - start over
|
|
|
|
arm_end_beep:
|
|
; Beep arm sequence end signal
|
|
clr IE_EA ; Disable all interrupts
|
|
call beep_f4 ; Signal that rcpulse is ready
|
|
call beep_f4
|
|
call beep_f4
|
|
setb IE_EA ; Enable all interrupts
|
|
call wait200ms
|
|
|
|
; Clear initial arm variable
|
|
mov Initial_Arm, #0
|
|
|
|
; Armed and waiting for power on
|
|
wait_for_power_on:
|
|
clr A
|
|
mov Power_On_Wait_Cnt_L, A ; Clear wait counter
|
|
mov Power_On_Wait_Cnt_H, A
|
|
wait_for_power_on_loop:
|
|
inc Power_On_Wait_Cnt_L ; Increment low wait counter
|
|
mov A, Power_On_Wait_Cnt_L
|
|
cpl A
|
|
jnz wait_for_power_on_no_beep; Counter wrapping (about 3 sec)
|
|
|
|
inc Power_On_Wait_Cnt_H ; Increment high wait counter
|
|
mov Temp1, #Pgm_Beacon_Delay
|
|
mov A, @Temp1
|
|
mov Temp1, #25 ; Approximately 1 min
|
|
dec A
|
|
jz beep_delay_set
|
|
|
|
mov Temp1, #50 ; Approximately 2 min
|
|
dec A
|
|
jz beep_delay_set
|
|
|
|
mov Temp1, #125 ; Approximately 5 min
|
|
dec A
|
|
jz beep_delay_set
|
|
|
|
mov Temp1, #250 ; Approximately 10 min
|
|
dec A
|
|
jz beep_delay_set
|
|
|
|
mov Power_On_Wait_Cnt_H, #0 ; Reset counter for infinite delay
|
|
|
|
beep_delay_set:
|
|
clr C
|
|
mov A, Power_On_Wait_Cnt_H
|
|
subb A, Temp1 ; Check against chosen delay
|
|
jc wait_for_power_on_no_beep; Has delay elapsed?
|
|
|
|
call switch_power_off ; Switch power off in case braking is set
|
|
call wait1ms
|
|
dec Power_On_Wait_Cnt_H ; Decrement high wait counter
|
|
mov Power_On_Wait_Cnt_L, #0 ; Set low wait counter
|
|
mov Temp1, #Pgm_Beacon_Strength
|
|
mov Beep_Strength, @Temp1
|
|
clr IE_EA ; Disable all interrupts
|
|
call beep_f4 ; Signal that there is no signal
|
|
setb IE_EA ; Enable all interrupts
|
|
mov Temp1, #Pgm_Beep_Strength
|
|
mov Beep_Strength, @Temp1
|
|
call wait100ms ; Wait for new RC pulse to be measured
|
|
|
|
wait_for_power_on_no_beep:
|
|
call wait10ms
|
|
mov A, Rcp_Timeout_Cntd ; Load RC pulse timeout counter value
|
|
jnz wait_for_power_on_not_missing ; If it is not zero - proceed
|
|
|
|
jmp init_no_signal ; If pulses missing - go back to detect input signal
|
|
|
|
wait_for_power_on_not_missing:
|
|
clr C
|
|
mov A, New_Rcp ; Load new RC pulse value
|
|
subb A, #1 ; Higher than stop
|
|
jnc wait_for_power_on_nonzero ; Yes - proceed
|
|
|
|
clr C
|
|
mov A, Dshot_Cmd
|
|
subb A, #1 ; 1 or higher
|
|
jnc check_dshot_cmd ; Check Dshot command
|
|
|
|
ljmp wait_for_power_on_loop ; If not Dshot command - start over
|
|
|
|
wait_for_power_on_nonzero:
|
|
lcall wait100ms ; Wait to see if start pulse was only a glitch
|
|
mov A, Rcp_Timeout_Cntd ; Load RC pulse timeout counter value
|
|
jnz ($+5) ; If it is not zero - proceed
|
|
ljmp init_no_signal ; If it is zero (pulses missing) - go back to detect input signal
|
|
|
|
mov Dshot_Cmd, #0
|
|
mov Dshot_Cmd_Cnt, #0
|
|
ljmp init_start
|
|
|
|
check_dshot_cmd:
|
|
clr C
|
|
mov A, Dshot_Cmd
|
|
subb A, #1
|
|
jnz dshot_beep_2
|
|
|
|
clr IE_EA
|
|
call switch_power_off ; Switch power off in case braking is set
|
|
mov Temp1, #Pgm_Beacon_Strength
|
|
mov Beep_Strength, @Temp1
|
|
call beep_f1
|
|
mov Temp1, #Pgm_Beep_Strength
|
|
mov Beep_Strength, @Temp1
|
|
setb IE_EA
|
|
call wait100ms
|
|
jmp clear_dshot_cmd
|
|
|
|
dshot_beep_2:
|
|
clr C
|
|
mov A, Dshot_Cmd
|
|
subb A, #2
|
|
jnz dshot_beep_3
|
|
|
|
clr IE_EA
|
|
call switch_power_off ; Switch power off in case braking is set
|
|
mov Temp1, #Pgm_Beacon_Strength
|
|
mov Beep_Strength, @Temp1
|
|
call beep_f2
|
|
mov Temp1, #Pgm_Beep_Strength
|
|
mov Beep_Strength, @Temp1
|
|
setb IE_EA
|
|
call wait100ms
|
|
jmp clear_dshot_cmd
|
|
|
|
dshot_beep_3:
|
|
clr C
|
|
mov A, Dshot_Cmd
|
|
subb A, #3
|
|
jnz dshot_beep_4
|
|
|
|
clr IE_EA
|
|
call switch_power_off ; Switch power off in case braking is set
|
|
mov Temp1, #Pgm_Beacon_Strength
|
|
mov Beep_Strength, @Temp1
|
|
call beep_f3
|
|
mov Temp1, #Pgm_Beep_Strength
|
|
mov Beep_Strength, @Temp1
|
|
setb IE_EA
|
|
call wait100ms
|
|
jmp clear_dshot_cmd
|
|
|
|
dshot_beep_4:
|
|
clr C
|
|
mov A, Dshot_Cmd
|
|
subb A, #4
|
|
jnz dshot_beep_5
|
|
|
|
clr IE_EA
|
|
call switch_power_off ; Switch power off in case braking is set
|
|
mov Temp1, #Pgm_Beacon_Strength
|
|
mov Beep_Strength, @Temp1
|
|
call beep_f4
|
|
mov Temp1, #Pgm_Beep_Strength
|
|
mov Beep_Strength, @Temp1
|
|
setb IE_EA
|
|
call wait100ms
|
|
jmp clear_dshot_cmd
|
|
|
|
dshot_beep_5:
|
|
clr C
|
|
mov A, Dshot_Cmd
|
|
subb A, #5
|
|
jnz dshot_direction_1
|
|
|
|
clr IE_EA
|
|
call switch_power_off ; Switch power off in case braking is set
|
|
mov Temp1, #Pgm_Beacon_Strength
|
|
mov Beep_Strength, @Temp1
|
|
call beep_f4
|
|
mov Temp1, #Pgm_Beep_Strength
|
|
mov Beep_Strength, @Temp1
|
|
setb IE_EA
|
|
call wait100ms
|
|
jmp clear_dshot_cmd
|
|
|
|
dshot_direction_1:
|
|
clr C
|
|
mov A, Dshot_Cmd
|
|
subb A, #7
|
|
jnz dshot_direction_2
|
|
|
|
clr C
|
|
mov A, Dshot_Cmd_Cnt
|
|
subb A, #6 ; Needs to receive it 6 times in a row
|
|
jnc ($+4) ; Same as "jc dont_clear_dshot_cmd"
|
|
ajmp wait_for_power_on_not_missing
|
|
|
|
mov A, #1
|
|
jnb Flags3.PGM_BIDIR, ($+5)
|
|
mov A, #3
|
|
mov Temp1, #Pgm_Direction
|
|
mov @Temp1, A
|
|
clr Flags3.PGM_DIR_REV
|
|
clr Flags3.PGM_BIDIR_REV
|
|
jmp clear_dshot_cmd
|
|
|
|
dshot_direction_2:
|
|
clr C
|
|
mov A, Dshot_Cmd
|
|
subb A, #8
|
|
jnz dshot_direction_bidir_off
|
|
|
|
clr C
|
|
mov A, Dshot_Cmd_Cnt
|
|
subb A, #6 ; Needs to receive it 6 times in a row
|
|
jnc ($+4) ; Same as "jc dont_clear_dshot_cmd"
|
|
ajmp wait_for_power_on_not_missing
|
|
|
|
mov A, #2
|
|
jnb Flags3.PGM_BIDIR, ($+5)
|
|
mov A, #4
|
|
mov Temp1, #Pgm_Direction
|
|
mov @Temp1, A
|
|
setb Flags3.PGM_DIR_REV
|
|
setb Flags3.PGM_BIDIR_REV
|
|
jmp clear_dshot_cmd
|
|
|
|
dshot_direction_bidir_off:
|
|
clr C
|
|
mov A, Dshot_Cmd
|
|
subb A, #9
|
|
jnz dshot_direction_bidir_on
|
|
|
|
clr C
|
|
mov A, Dshot_Cmd_Cnt
|
|
subb A, #6 ; Needs to receive it 6 times in a row
|
|
jnc ($+4) ; Same as "jc dont_clear_dshot_cmd"
|
|
ajmp wait_for_power_on_not_missing
|
|
|
|
jnb Flags3.PGM_BIDIR, dshot_direction_bidir_on
|
|
|
|
clr C
|
|
mov Temp1, #Pgm_Direction
|
|
mov A, @Temp1
|
|
subb A, #2
|
|
mov @Temp1, A
|
|
clr Flags3.PGM_BIDIR
|
|
jmp clear_dshot_cmd
|
|
|
|
dshot_direction_bidir_on:
|
|
clr C
|
|
mov A, Dshot_Cmd
|
|
subb A, #10
|
|
jnz dshot_direction_normal
|
|
|
|
clr C
|
|
mov A, Dshot_Cmd_Cnt
|
|
subb A, #6 ; Needs to receive it 6 times in a row
|
|
jnc ($+4) ; Same as "jc dont_clear_dshot_cmd"
|
|
ajmp wait_for_power_on_not_missing
|
|
|
|
jb Flags3.PGM_BIDIR, dshot_direction_normal
|
|
|
|
mov Temp1, #Pgm_Direction
|
|
mov A, @Temp1
|
|
add A, #2
|
|
mov @Temp1, A
|
|
setb Flags3.PGM_BIDIR
|
|
jmp clear_dshot_cmd
|
|
|
|
dshot_direction_normal:
|
|
clr C
|
|
mov A, Dshot_Cmd
|
|
subb A, #20
|
|
jnz dshot_direction_reverse
|
|
|
|
clr C
|
|
mov A, Dshot_Cmd_Cnt
|
|
subb A, #6 ; Needs to receive it 6 times in a row
|
|
jnc ($+4) ; Same as "jc dont_clear_dshot_cmd"
|
|
ajmp wait_for_power_on_not_missing
|
|
|
|
clr IE_EA ; DPTR used in interrupts
|
|
mov DPTR, #Eep_Pgm_Direction ; Read from flash
|
|
mov A, #0
|
|
movc A, @A+DPTR
|
|
setb IE_EA
|
|
mov Temp1, #Pgm_Direction
|
|
mov @Temp1, A
|
|
rrc A ; Lsb to carry
|
|
clr Flags3.PGM_DIR_REV
|
|
clr Flags3.PGM_BIDIR_REV
|
|
jc ($+4)
|
|
setb Flags3.PGM_DIR_REV
|
|
jc ($+4)
|
|
setb Flags3.PGM_BIDIR_REV
|
|
jmp clear_dshot_cmd
|
|
|
|
dshot_direction_reverse: ; Temporary reverse
|
|
clr C
|
|
mov A, Dshot_Cmd
|
|
subb A, #21
|
|
jnz dshot_save_settings
|
|
|
|
clr C
|
|
mov A, Dshot_Cmd_Cnt
|
|
subb A, #6 ; Needs to receive it 6 times in a row
|
|
jc dont_clear_dshot_cmd
|
|
|
|
clr IE_EA ; DPTR used in interrupts
|
|
mov DPTR, #Eep_Pgm_Direction ; Read from flash
|
|
mov A, #0
|
|
movc A, @A+DPTR
|
|
setb IE_EA
|
|
mov Temp1, A
|
|
cjne Temp1, #1, ($+5)
|
|
mov A, #2
|
|
cjne Temp1, #2, ($+5)
|
|
mov A, #1
|
|
cjne Temp1, #3, ($+5)
|
|
mov A, #4
|
|
cjne Temp1, #4, ($+5)
|
|
mov A, #3
|
|
mov Temp1, #Pgm_Direction
|
|
mov @Temp1, A
|
|
rrc A ; Lsb to carry
|
|
clr Flags3.PGM_DIR_REV
|
|
clr Flags3.PGM_BIDIR_REV
|
|
jc ($+4)
|
|
setb Flags3.PGM_DIR_REV
|
|
jc ($+4)
|
|
setb Flags3.PGM_BIDIR_REV
|
|
jmp clear_dshot_cmd
|
|
|
|
dshot_save_settings:
|
|
clr C
|
|
mov A, Dshot_Cmd
|
|
subb A, #12
|
|
jnz clear_dshot_cmd
|
|
|
|
mov Flash_Key_1, #0A5h ; Initialize flash keys to valid values
|
|
mov Flash_Key_2, #0F1h
|
|
clr C
|
|
mov A, Dshot_Cmd_Cnt
|
|
subb A, #6 ; Needs to receive it 6 times in a row
|
|
jc dont_clear_dshot_cmd
|
|
|
|
call erase_and_store_all_in_eeprom
|
|
setb IE_EA
|
|
|
|
clear_dshot_cmd:
|
|
mov Dshot_Cmd, #0
|
|
mov Dshot_Cmd_Cnt, #0
|
|
|
|
dont_clear_dshot_cmd:
|
|
mov Flash_Key_1, #0 ; Initialize flash keys to invalid values
|
|
mov Flash_Key_2, #0
|
|
jmp wait_for_power_on_not_missing
|
|
|
|
;**** **** **** **** **** **** **** **** **** **** **** **** ****
|
|
;
|
|
; Start entry point
|
|
;
|
|
;**** **** **** **** **** **** **** **** **** **** **** **** ****
|
|
init_start:
|
|
clr IE_EA
|
|
call switch_power_off
|
|
clr A
|
|
setb IE_EA
|
|
clr A
|
|
mov Adc_Conversion_Cnt, A
|
|
mov Flags0, A ; Clear flags0
|
|
mov Flags1, A ; Clear flags1
|
|
mov Demag_Detected_Metric, A ; Clear demag metric
|
|
;**** **** **** **** ****
|
|
; Motor start beginning
|
|
;**** **** **** **** ****
|
|
mov Adc_Conversion_Cnt, #8 ; Make sure a temp reading is done
|
|
call wait1ms
|
|
call start_adc_conversion
|
|
read_initial_temp:
|
|
jnb ADC0CN0_ADINT, read_initial_temp
|
|
Read_Adc_Result ; Read initial temperature
|
|
mov A, Temp2
|
|
jnz ($+3) ; Is reading below 256?
|
|
|
|
mov Temp1, A ; Yes - set average temperature value to zero
|
|
|
|
mov Current_Average_Temp, Temp1 ; Set initial average temperature
|
|
call check_temp_voltage_and_limit_power
|
|
mov Adc_Conversion_Cnt, #8 ; Make sure a temp reading is done next time
|
|
; Set up start operating conditions
|
|
clr IE_EA ; Disable interrupts
|
|
call set_startup_pwm
|
|
mov Pwm_Limit, Pwm_Limit_Beg
|
|
mov Pwm_Limit_By_Rpm, Pwm_Limit_Beg
|
|
setb IE_EA
|
|
; Begin startup sequence
|
|
IF MCU_48MHZ == 1
|
|
Set_MCU_Clk_48MHz
|
|
ENDIF
|
|
jnb Flags3.PGM_BIDIR, init_start_bidir_done ; Check if bidirectional operation
|
|
|
|
clr Flags3.PGM_DIR_REV ; Set spinning direction. Default fwd
|
|
jnb Flags2.RCP_DIR_REV, ($+5) ; Check force direction
|
|
setb Flags3.PGM_DIR_REV ; Set spinning direction
|
|
|
|
init_start_bidir_done:
|
|
setb Flags1.STARTUP_PHASE ; Set startup phase flag
|
|
mov Startup_Cnt, #0 ; Reset counter
|
|
call comm5comm6 ; Initialize commutation
|
|
call comm6comm1
|
|
call initialize_timing ; Initialize timing
|
|
call calc_next_comm_timing ; Set virtual commutation point
|
|
call initialize_timing ; Initialize timing
|
|
call calc_next_comm_timing
|
|
call initialize_timing ; Initialize timing
|
|
|
|
|
|
|
|
;**** **** **** **** **** **** **** **** **** **** **** **** ****
|
|
;
|
|
; Run entry point
|
|
;
|
|
;**** **** **** **** **** **** **** **** **** **** **** **** ****
|
|
|
|
; Run 1 = B(p-on) + C(n-pwm) - comparator A evaluated
|
|
; Out_cA changes from low to high
|
|
run1:
|
|
call wait_for_comp_out_high ; Wait for high
|
|
; setup_comm_wait ; Setup wait time from zero cross to commutation
|
|
; evaluate_comparator_integrity ; Check whether comparator reading has been normal
|
|
call wait_for_comm ; Wait from zero cross to commutation
|
|
call comm1comm2 ; Commutate
|
|
call calc_next_comm_timing ; Calculate next timing and wait advance timing wait
|
|
; wait_advance_timing ; Wait advance timing and start zero cross wait
|
|
; calc_new_wait_times
|
|
; wait_before_zc_scan ; Wait zero cross wait and start zero cross timeout
|
|
|
|
; Run 2 = A(p-on) + C(n-pwm) - comparator B evaluated
|
|
; Out_cB changes from high to low
|
|
run2:
|
|
call wait_for_comp_out_low
|
|
; setup_comm_wait
|
|
; evaluate_comparator_integrity
|
|
jb Flags1.HIGH_RPM, ($+6) ; Skip if high rpm
|
|
lcall set_pwm_limit_low_rpm
|
|
jnb Flags1.HIGH_RPM, ($+6) ; Do if high rpm
|
|
lcall set_pwm_limit_high_rpm
|
|
call wait_for_comm
|
|
call comm2comm3
|
|
call calc_next_comm_timing
|
|
; wait_advance_timing
|
|
; calc_new_wait_times
|
|
; wait_before_zc_scan
|
|
|
|
; Run 3 = A(p-on) + B(n-pwm) - comparator C evaluated
|
|
; Out_cC changes from low to high
|
|
run3:
|
|
call wait_for_comp_out_high
|
|
; setup_comm_wait
|
|
; evaluate_comparator_integrity
|
|
call wait_for_comm
|
|
call comm3comm4
|
|
call calc_next_comm_timing
|
|
; wait_advance_timing
|
|
; calc_new_wait_times
|
|
; wait_before_zc_scan
|
|
|
|
; Run 4 = C(p-on) + B(n-pwm) - comparator A evaluated
|
|
; Out_cA changes from high to low
|
|
run4:
|
|
call wait_for_comp_out_low
|
|
; setup_comm_wait
|
|
; evaluate_comparator_integrity
|
|
call wait_for_comm
|
|
call comm4comm5
|
|
call calc_next_comm_timing
|
|
; wait_advance_timing
|
|
; calc_new_wait_times
|
|
; wait_before_zc_scan
|
|
|
|
; Run 5 = C(p-on) + A(n-pwm) - comparator B evaluated
|
|
; Out_cB changes from low to high
|
|
run5:
|
|
call wait_for_comp_out_high
|
|
; setup_comm_wait
|
|
; evaluate_comparator_integrity
|
|
call wait_for_comm
|
|
call comm5comm6
|
|
call calc_next_comm_timing
|
|
; wait_advance_timing
|
|
; calc_new_wait_times
|
|
; wait_before_zc_scan
|
|
|
|
; Run 6 = B(p-on) + A(n-pwm) - comparator C evaluated
|
|
; Out_cC changes from high to low
|
|
run6:
|
|
call start_adc_conversion
|
|
call wait_for_comp_out_low
|
|
; setup_comm_wait
|
|
; evaluate_comparator_integrity
|
|
call wait_for_comm
|
|
call comm6comm1
|
|
call check_temp_voltage_and_limit_power
|
|
call calc_next_comm_timing
|
|
; wait_advance_timing
|
|
; calc_new_wait_times
|
|
; wait_before_zc_scan
|
|
|
|
; Check if it is direct startup
|
|
jnb Flags1.STARTUP_PHASE, normal_run_checks
|
|
|
|
; Set spoolup power variables
|
|
mov Pwm_Limit, Pwm_Limit_Beg ; Set initial max power
|
|
; Check startup counter
|
|
mov Temp2, #24 ; Set nominal startup parameters
|
|
mov Temp3, #12
|
|
clr C
|
|
mov A, Startup_Cnt ; Load counter
|
|
subb A, Temp2 ; Is counter above requirement?
|
|
jc direct_start_check_rcp ; No - proceed
|
|
|
|
clr Flags1.STARTUP_PHASE ; Clear startup phase flag
|
|
setb Flags1.INITIAL_RUN_PHASE ; Set initial run phase flag
|
|
mov Initial_Run_Rot_Cntd, Temp3 ; Set initial run rotation count
|
|
mov Pwm_Limit, Pwm_Limit_Beg
|
|
mov Pwm_Limit_By_Rpm, Pwm_Limit_Beg
|
|
jmp normal_run_checks
|
|
|
|
direct_start_check_rcp:
|
|
clr C
|
|
mov A, New_Rcp ; Load new pulse value
|
|
subb A, #1 ; Check if pulse is below stop value
|
|
jc ($+5)
|
|
|
|
ljmp run1 ; Continue to run
|
|
|
|
jmp run_to_wait_for_power_on
|
|
|
|
|
|
normal_run_checks:
|
|
; Check if it is initial run phase
|
|
jnb Flags1.INITIAL_RUN_PHASE, initial_run_phase_done ; If not initial run phase - branch
|
|
jb Flags1.DIR_CHANGE_BRAKE, initial_run_phase_done ; If a direction change - branch
|
|
|
|
; Decrement startup rotaton count
|
|
mov A, Initial_Run_Rot_Cntd
|
|
dec A
|
|
; Check number of initial rotations
|
|
jnz initial_run_check_startup_rot ; Branch if counter is not zero
|
|
|
|
clr Flags1.INITIAL_RUN_PHASE ; Clear initial run phase flag
|
|
setb Flags1.MOTOR_STARTED ; Set motor started
|
|
jmp run1 ; Continue with normal run
|
|
|
|
initial_run_check_startup_rot:
|
|
mov Initial_Run_Rot_Cntd, A ; Not zero - store counter
|
|
|
|
jb Flags3.PGM_BIDIR, initial_run_continue_run ; Check if bidirectional operation
|
|
|
|
clr C
|
|
mov A, New_Rcp ; Load new pulse value
|
|
subb A, #1 ; Check if pulse is below stop value
|
|
jc ($+5)
|
|
|
|
initial_run_continue_run:
|
|
ljmp run1 ; Continue to run
|
|
|
|
jmp run_to_wait_for_power_on
|
|
|
|
initial_run_phase_done:
|
|
; Reset stall count
|
|
mov Stall_Cnt, #0
|
|
; Exit run loop after a given time
|
|
jb Flags3.PGM_BIDIR, run6_check_timeout ; Check if bidirectional operation
|
|
|
|
mov Temp1, #250
|
|
mov Temp2, #Pgm_Brake_On_Stop
|
|
mov A, @Temp2
|
|
jz ($+4)
|
|
|
|
mov Temp1, #3 ; About 100ms before stopping when brake is set
|
|
|
|
clr C
|
|
mov A, Rcp_Stop_Cnt ; Load stop RC pulse counter low byte value
|
|
subb A, Temp1 ; Is number of stop RC pulses above limit?
|
|
jnc run_to_wait_for_power_on ; Yes, go back to wait for poweron
|
|
|
|
run6_check_timeout:
|
|
mov A, Rcp_Timeout_Cntd ; Load RC pulse timeout counter value
|
|
jz run_to_wait_for_power_on ; If it is zero - go back to wait for poweron
|
|
|
|
run6_check_dir:
|
|
jnb Flags3.PGM_BIDIR, run6_check_speed ; Check if bidirectional operation
|
|
|
|
jb Flags3.PGM_DIR_REV, run6_check_dir_rev ; Check if actual rotation direction
|
|
jb Flags2.RCP_DIR_REV, run6_check_dir_change ; Matches force direction
|
|
jmp run6_check_speed
|
|
|
|
run6_check_dir_rev:
|
|
jnb Flags2.RCP_DIR_REV, run6_check_dir_change
|
|
jmp run6_check_speed
|
|
|
|
run6_check_dir_change:
|
|
jb Flags1.DIR_CHANGE_BRAKE, run6_check_speed
|
|
|
|
setb Flags1.DIR_CHANGE_BRAKE ; Set brake flag
|
|
mov Pwm_Limit, Pwm_Limit_Beg ; Set max power while braking
|
|
jmp run4 ; Go back to run 4, thereby changing force direction
|
|
|
|
run6_check_speed:
|
|
mov Temp1, #0F0h ; Default minimum speed
|
|
jnb Flags1.DIR_CHANGE_BRAKE, run6_brake_done; Is it a direction change?
|
|
|
|
mov Pwm_Limit, Pwm_Limit_Beg ; Set max power while braking
|
|
mov Temp1, #20h ; Bidirectional braking termination speed
|
|
|
|
run6_brake_done:
|
|
clr C
|
|
mov A, Comm_Period4x_H ; Is Comm_Period4x more than 32ms (~1220 eRPM)?
|
|
subb A, Temp1
|
|
jnc ($+5) ; Yes - stop or turn direction
|
|
ljmp run1 ; No - go back to run 1
|
|
|
|
jnb Flags1.DIR_CHANGE_BRAKE, run_to_wait_for_power_on ; If it is not a direction change - stop
|
|
|
|
clr Flags1.DIR_CHANGE_BRAKE ; Clear brake flag
|
|
clr Flags3.PGM_DIR_REV ; Set spinning direction. Default fwd
|
|
jnb Flags2.RCP_DIR_REV, ($+5) ; Check force direction
|
|
setb Flags3.PGM_DIR_REV ; Set spinning direction
|
|
setb Flags1.INITIAL_RUN_PHASE
|
|
mov Initial_Run_Rot_Cntd, #18
|
|
mov Pwm_Limit, Pwm_Limit_Beg ; Set initial max power
|
|
jmp run1 ; Go back to run 1
|
|
|
|
run_to_wait_for_power_on_fail:
|
|
inc Stall_Cnt ; Increment stall count
|
|
mov A, New_Rcp ; Check if RCP is zero, then it is a normal stop
|
|
jz run_to_wait_for_power_on
|
|
ajmp run_to_wait_for_power_on_stall_done
|
|
|
|
run_to_wait_for_power_on:
|
|
mov Stall_Cnt, #0
|
|
|
|
run_to_wait_for_power_on_stall_done:
|
|
clr IE_EA
|
|
call switch_power_off
|
|
mov Flags0, #0 ; Clear flags0
|
|
mov Flags1, #0 ; Clear flags1
|
|
IF MCU_48MHZ == 1
|
|
Set_MCU_Clk_24MHz
|
|
ENDIF
|
|
setb IE_EA
|
|
call wait100ms ; Wait for pwm to be stopped
|
|
call switch_power_off
|
|
mov Temp1, #Pgm_Brake_On_Stop
|
|
mov A, @Temp1
|
|
jz run_to_wait_for_power_on_brake_done
|
|
|
|
AcomFET_on
|
|
BcomFET_on
|
|
CcomFET_on
|
|
|
|
run_to_wait_for_power_on_brake_done:
|
|
clr C
|
|
mov A, Stall_Cnt
|
|
subb A, #4
|
|
jc jmp_wait_for_power_on
|
|
jmp init_no_signal
|
|
|
|
jmp_wait_for_power_on:
|
|
jmp wait_for_power_on ; Go back to wait for power on
|
|
|
|
;**** **** **** **** **** **** **** **** **** **** **** **** ****
|
|
|
|
$include (BLHeliPgm.inc) ; Include source code for programming the ESC
|
|
$include (BLHeliBootLoad.inc) ; Include source code for bootloader
|
|
|
|
;**** **** **** **** **** **** **** **** **** **** **** **** ****
|
|
|
|
|
|
|
|
CSEG AT 19FDh
|
|
reset:
|
|
ljmp pgm_start
|
|
|
|
|
|
|
|
END
|