Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. ;throttle_momentum.asm
  2.  
  3. .NOLIST
  4.  
  5. ;  ***************************************************************************************
  6. ;  * PWM MODEL RAILROAD THROTTLE                                                          *
  7. ;  *                                                                                      *
  8. ;  * WRITTEN BY:  PHILIP DEVRIES                                                          *
  9. ;  *                                                                                      *
  10. ;  *  Copyright (C) 2003 Philip DeVries                                                   *
  11. ;  *                                                                                      *
  12. ;  *  This program is free software; you can redistribute it and/or modify                *
  13. ;  *  it under the terms of the GNU General Public License as published by                *
  14. ;  *  the Free Software Foundation; either version 2 of the License, or                   *
  15. ;  *  (at your option) any later version.                                                 *
  16. ;  *                                                                                      *
  17. ;  *  This program is distributed in the hope that it will be useful,                     *
  18. ;  *  but WITHOUT ANY WARRANTY; without even the implied warranty of                      *
  19. ;  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                       *
  20. ;  *  GNU General Public License for more details.                                        *
  21. ;  *                                                                                      *
  22. ;  *  You should have received a copy of the GNU General Public License                   *
  23. ;  *  along with this program; if not, write to the Free Software                         *
  24. ;  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA           *
  25. ;  *                                                                                      *
  26. ;  ***************************************************************************************:
  27. .LIST
  28.  
  29. .ifdef MOMENTUM_ENABLED
  30. ;********************************************************************************
  31. ;* MOMENTUM_ADJUST                                                               *
  32. ;* Top level routine                                                             *
  33. ;*                                                                               *
  34. ;* Momentum simulates the mass of the train.  Since model trains have little     *
  35. ;* mass, the locomotive speed can directly follow the throttle setting; in       *
  36. ;* other words, a model train can accelerate and decelerate instantly.           *
  37. ;* Real trains are very massive, and therefore they do not accelerate or         *
  38. ;* decelerate quickly.                                                           *
  39. ;*                                                                               *
  40. ;* According to Newtons law, the acceleration is proportional to the force,      *
  41. ;* and inversely proportional to the mass.  Therefore, the more massive the      *
  42. ;* train, the more slowly the train will accelerate or decelerate.  Also, the    *
  43. ;* more force the locomotive can provide, the faster the train will accelerate.  *
  44. ;* Deceler depends on the braking capability of the overall train.               *
  45. ;*                                                                               *
  46. ;* If force were constant, Newtons law states that acceleration would be         *
  47. ;* constant too.  This subroutine assumes that somewhat more force is            *
  48. ;* available at low speeds than at high speeds, so that acceleration will be     *
  49. ;* greater at low speeds.  The subroutine also assumes that opposing forces      *
  50. ;* (friction, wind resistance, etc) are stronger at higher speeds.  This         *
  51. ;* assumption also means that acceleration will be greater at low speeds.        *
  52. ;*                                                                               *
  53. ;* This subroutine calculates acceleration/deceleration by this simple           *
  54. ;* Method:                                                                       *
  55. ;*                                                                               *
  56. ;*    The rate of speed change (accleration and deceleration) depends on the     *
  57. ;*    current speed as                                                           *
  58. ;*    {Speed_Max (0xFF) - Current_Speed} / {Tau*Rate}                            *
  59. ;*                                                                               *
  60. ;*       Where    T = index of sample time                                       *
  61. ;*                t = real time                                                  *
  62. ;*                Tau = time constant                                            *
  63. ;*                Rate = Update rate (nominally 100Hz)                           *
  64. ;*                                                                               *
  65. ;* That is, the acceleration/deceleration is maximum at zero speed, and          *
  66. ;* approaches zero at maximum speed.                                             *
  67. ;*                                                                               *
  68. ;* When accelerating, the speed at the next sample period is                     *
  69. ;*    Speed(T) = Speed(T-1) + {0xFF - Speed(T-1)} / {Tau*Rate}                   *
  70. ;*                                                                               *
  71. ;*    Giving an acceleration curve that looks like a normal exponential.         *
  72. ;*    Speed(t) = 0xFF { 1 - exp( - t / Tau) }                                    *
  73. ;*                                                                               *
  74. ;*                                        *                   *                  *
  75. ;*                       *                                                       *
  76. ;*             *                                                                 *
  77. ;*         *                                                                     *
  78. ;*       *                                                                       *
  79. ;*      *                                                                        *
  80. ;*     *                                                                         *
  81. ;*     *                                                                         *
  82. ;*                                                                               *
  83. ;*                                                                               *
  84. ;* When decelerating, the change rate equation is the same, but the change       *
  85. ;* is subtracted, as                                                             *
  86. ;*    Speed(T) = Speed(T) - {0xFF - Speed(T-1)} / {Tau*Rate}                     *
  87. ;*                                                                               *
  88. ;*    Giving a deceleration curve that looks like                                *
  89. ;*    Speed(t) = 0xFF { 1 - exp( -(T1 - t) / Tau) }                              *
  90. ;* which is a mirror image of the acceleration, NOT a normal exponential.        *
  91. ;*                                                                               *
  92. ;*     *              *                                                          *
  93. ;*                                        *                                      *
  94. ;*                                            *                                  *
  95. ;*                                              *                                *
  96. ;*                                               *                               *
  97. ;*                                                *                              *
  98. ;*                                                *                              *
  99. ;*                                                                               *
  100. ;*                                                                               *
  101. ;* In each case, the acceleration or deceleration is "clipped" at the current    *
  102. ;* throttle setting so that the speed doesn't overshoot or undershoot.           *
  103. ;*                                                                               *
  104. ;* Three different values of Tau are used, that is                               *
  105. ;*    Tau_accel      Corresponding to acceleration under power                   *
  106. ;*    Tau_coast      Corresponding to deceleration when coasting                 *
  107. ;*    Tau_brake      Corresponding to deceleration when braking                  *
  108. ;*                                                                               *
  109. ;* To permit finer control of momentum, the throttle setting is converted to a   *
  110. ;* 16 bit number, where the 8 msb's correspond to the throttle setting from      *
  111. ;* the throttle handle and sent forward.                                         *
  112. ;*                                                                               *
  113. ;* Inputs:  throttle_set      Throttle handle position ( 0x00 to 0xFF )          *
  114. ;*          speed_hi_prev     Hi byte of (T-1) throttle setting (stored)         *
  115. ;*          speed_lo_prev     Lo byte of (T-1) throttle setting (stored)         *
  116. ;* Returns: throttle_set      Adjusted throttle setting (T)                      *
  117. ;*          speed_hi_prev     Hi byte of (T) throttle setting  (stored)          *
  118. ;*          speed_lo_prev     Lo byte of (T) throttle setting  (stored)          *
  119. ;* Changed: B_Temp                                                               *
  120. ;*          B_Temp1                                                              *
  121. ;*          B_Temp2                                                              *
  122. ;*          B_Temp3                                                              *
  123. ;* Calls:   NONE                                                                 *  
  124. ;* Goto:    MOMENTUM_ADJUST_RETURN                                               *
  125. ;********************************************************************************
  126.    B_TEMPLOCAL2 _time_constant_adj
  127.  
  128.  
  129. .ifdef TRADITIONAL_ENABLED
  130.    .ifdef LEDS_ENABLED
  131.       sbrc  Flags_1,BF_brake           ; If the brake flag is set,
  132.       sbi   PORTB,dir_in_port          ; Port Output: Indicate deceleration
  133.    .endif ;LEDS_ENABLED
  134. .endif ;TRADITIONAL_ENABLED
  135.  
  136.    ;*******************************************************************
  137.    ;* Adjust the value of "momentum_set".
  138.    ;* This adjustment makes it easier to fine adjust low momentum settings
  139.    ;* while still permitting large momentum settings.
  140.    ;*
  141.    ;* The ammount of momentum to apply comes in in "momentum_set"
  142.    ;* which is read in READ_THROTTLE.  The nominal range is
  143.    ;* 0x00 to 0x40.  This value is multiplied by two and squared,
  144.    ;* giving a new range from 0x00 to 0x4000.  The update rate is 100Hz,
  145.    ;* and so the new range corresponds to a time constant from
  146.    ;* 0(decimal) to 164(decimal) seconds.  Since the adjustment was
  147.    ;* done by performing a square, the adjusted value is non-linear
  148.    ;* with the input value.
  149.    ;*******************************************************************
  150.    lsl   momentum_set                        ; multiply by two
  151.  
  152.    HILOCAL1    _mset_multiplier              ; supply to mpy8u
  153.    B_TEMPLOCAL _mset_multiplicand            ; supply to mpy8u
  154.  
  155.    mov   _mset_multiplier,momentum_set       ;  
  156.    mov   _mset_multiplicand,momentum_set     ;
  157.    rcall mpy8u                               ; square
  158.  
  159.    B_TEMPLOCAL1   _mset_hi_byte              ; return from mpy8u
  160.    B_TEMPLOCAL    _mset_lo_byte              ; return from mpy8u
  161.  
  162.    ;*******************************************************************
  163.    ;* Compute the difference between the maximum throttle and
  164.    ;* the current throttle
  165.    ;*******************************************************************
  166.    HILOCAL2 _mset_diff_hi_byte
  167.    HILOCAL1 _mset_diff_lo_byte
  168.  
  169.    ldi   _mset_diff_hi_byte,0xFF             ; Maximum possible speed
  170.    ldi   _mset_diff_lo_byte,0xFF             ;                      
  171.  
  172.    sub   _mset_diff_lo_byte,speed_lo_prev    ; Difference between max speed
  173.    sbc   _mset_diff_hi_byte,speed_hi_prev    ; and current speed
  174.  
  175.    ;*******************************************************************
  176.    ;* Determine whether to accelerate, decelerate, or remain unchanged.
  177.    ;* Compare the throttle handle setting with the actual speed
  178.    ;*******************************************************************
  179.    cp    throttle_set,speed_hi_prev    ; Test if throttle position is larger
  180.                                        ; or smaller than the speed.
  181.  
  182.    breq  EVEN_SPEED                    ; If the throttle position is the same
  183.                                        ; as the speed.
  184.                                        
  185.    brlo  SETUP_DECELERATE              ; If the throttle position is smaller
  186.                                        ; than the speed, then need to decelerate.
  187.  
  188. ;  brsh  SETUP_ACCELERATE              ; If the throttle position is larger
  189.                                        ; than the speed, then need to accelerate.
  190.  
  191. SETUP_ACCELERATE:
  192. .ifdef TRADITIONAL_ENABLED
  193.    .ifdef LEDS_ENABLED
  194.       cpi   throttle_set,accel_led_threshold ; If the throttle is less than minimum
  195.       brlo  END_SET_ACCEL_LED                ; don't light led
  196.  
  197.       mov   B_Temp2,throttle_set             ; If the throttle is closer than led_threshold
  198.       subi  B_Temp2,accel_led_threshold      ; don't light led
  199.       cp    B_Temp2,speed_hi_prev      
  200.       brlo  END_SET_ACCEL_LED
  201.  
  202.       sbi   PORTB,momentum_port        ; Port Output: Indicate acceleration
  203.       END_SET_ACCEL_LED:
  204.    .endif LEDS_ENABLED
  205. .endif TRADITIONAL_ENABLED
  206.  
  207.    sbr   Flags_1,F_accel               ; Set accelerating flag
  208.                                        ; Indicate acceleration
  209.  
  210.    ldi   _time_constant_adj,accel_offset+1   ; Acceleration time constant adjust
  211.  
  212.    rjmp  CHECK_BRAKE
  213.  
  214. EVEN_SPEED:                            ; Arrive here if throttle_set=current speed
  215.  
  216.    sbrc  Flags_1,BF_brake              ; If the brake flag is set, decelerate
  217.    rjmp  CHECK_BRAKE                   ;
  218.  
  219.    rjmp  DONE_WITH_MOMENTUM            ; Otherwise adjustment is necessary
  220.  
  221.  
  222. SETUP_DECELERATE:
  223.    cbr   Flags_1,F_accel               ; Clear accelerating flag
  224.  
  225. .ifdef TRADITIONAL_ENABLED
  226.    .ifdef LEDS_ENABLED
  227.  
  228.       cpi   throttle_set,0xff-decel_led_threshold  ; If the throttle is more than maximum
  229.       brsh  END_SET_DECEL_LED                      ; don't light led
  230.  
  231.       mov   B_Temp2,throttle_set
  232.       subi  B_Temp2,0x00-decel_led_threshold       ; If the throttle is closer than the led
  233.       cp    B_Temp2,speed_hi_prev                  ; threshold, don't light the led
  234.       brsh  END_SET_DECEL_LED
  235.  
  236.       sbi   PORTB,dir_in_port          ; Port Output: Indicate deceleration
  237.       END_SET_DECEL_LED:
  238.    .endif LEDS_ENABLED
  239. .endif TRADITIONAL_ENABLED
  240.  
  241.    ldi   _time_constant_adj,0+1       ; Coasting deceleration time const. adjust.
  242. ;  rjmp  CHECK_BRAKE
  243.  
  244. CHECK_BRAKE:                           ; Always check for the brake.
  245.  
  246.    sbrs  Flags_1,BF_brake              ; If brake flag is not set,
  247.    rjmp  ADJUST_TAU                    ; proceed.  
  248.  
  249.                                        ; Brake overrides acceleration
  250.                                        ; or coasting.
  251.    cbr   Flags_1,F_accel               ; clear accelerating flag
  252.                                        ; Indicate deceleration
  253.  
  254.    ldi   _time_constant_adj,brake_offset+1   ; Braking deceleration time const. adjust.
  255.  
  256. ;  rjmp  ADJUST_TAU
  257.  
  258. ADJUST_TAU:
  259.    ;B_TEMP2=B_TEMPLOCAL2
  260.    dec   _time_constant_adj            ; Divide tau_base by 2^_time_constant_adj
  261.    breq  DIVIDE_TAU                    ; to produce adjusted tau.
  262.  
  263.    lsr   _mset_hi_byte                              
  264.    ror   _mset_lo_byte
  265.    rjmp  ADJUST_TAU
  266.  
  267. DIVIDE_TAU:
  268.    sbr   _mset_lo_byte,0b00000001      ; Force last bit 1.  Prevent divide by zero.
  269.  
  270.    rcall div16u                        ; Divide _mset_diff_hi_byte:_mset_diff_lo_byte
  271.                                        ;  (difference)
  272.                                        ; by _mset_hi_byte:_mset_lo_byte (dividor)
  273.  
  274.    sbrs  Flags_1,BF_accel              ; add or subtract change depending
  275.    rjmp  SUBTRACT_CHANGE               ; on F_accel flag
  276.    ;rjmp ADD_CHANGE
  277.  
  278. ADD_CHANGE:                            ; Case accelerating
  279.  
  280. ;  HILOCAL2 _mset_diff_hi_byte
  281. ;  HILOCAL1 _mset_diff_lo_byte
  282.  
  283.    add   speed_lo_prev,_mset_diff_lo_byte        ; Add in the change
  284.    adc   speed_hi_prev,_mset_diff_hi_byte
  285.  
  286.    cp    throttle_set,speed_hi_prev    ; If larger than the throttle_set value
  287.    brlo  USE_SET_SPEED                 ; clamp at throttle_set value                
  288.  
  289.    rjmp  DONE_WITH_MOMENTUM
  290.  
  291. SUBTRACT_CHANGE:                       ; Case decelerating
  292.  
  293.    sbrc  Flags_1,BF_brake              ; If the brake flag is set,
  294.    clr   throttle_set                  ; decelerate all the way to zero
  295.  
  296.    sub   speed_lo_prev,_mset_diff_lo_byte        ; Subtract the change
  297.    sbc   speed_hi_prev,_mset_diff_hi_byte        ;
  298.  
  299.    brlo  USE_SET_SPEED                 ; If less than zero
  300.                                        ; clamp at throttle_set value
  301.  
  302.    cp    speed_hi_prev,throttle_set    ; If less than the throttle_set value
  303.    brlo  USE_SET_SPEED                 ; clamp at throttle_set value
  304.  
  305.    rjmp  DONE_WITH_MOMENTUM
  306.  
  307. USE_SET_SPEED:                         ; Use the throttle_set value directly
  308.    mov   speed_hi_prev,throttle_set
  309.    clr   speed_lo_prev
  310.  
  311. DONE_WITH_MOMENTUM:
  312.    mov   throttle_set,speed_hi_prev    ; Put the new value into throttle_set.
  313.  
  314. .endif ;MOMENTUM_ENABLED
  315.