(* Exx - For noForth 2553 lp.0, C&V version: miniature DC motor driver
   that can be used as digital servo driver too.

  Pulswidth power control with 1 KHz PWM with a resolution of 1000 steps

  Address 020 = P1IN, port-1 input register
  Address 021 = P1OUT, port-1 output register
  Address 022 = P1DIR, port-1 direction register
  Address 027 = P1REN, port-1 resistor enable
  Address 029 = P2OUT, port-2 output with 8 leds
  Address 02A = P2DIR, port-2 direction register
  Address 02E = P2SEL, port-2 selection register

  Address 180 = TA1CTL, timer a1 compare mode
  Address 186 = TA1CCTL2, timer a1 output mode
  Address 192 = TA1CCR0, timer a1 period timing
  Address 196 = TA1CCR2, timer a1 Duty cycle

  Address 04A - ADC10AE0, ADC analog enable 0
  Address 1B0 - ADC10CTL0, ADC controle register 0
  Address 1B2 - ADC10CTL1, ADC controle register 1
  Address 1B4 - ADC10MEM, ADC memory

  * More info about the ADC10, in SLAU144J.PDF on page 533 and beyond.

 *)

hex

(* Documentation about ADC10:

This a rewritten version of ADC10 single conversion implementation.
It has to be tested if this version is more robust!

Note that to do a correct conversion and/or improve the speed,
the correct sample time must be selected. The formula is:

tsample > (RS + 2000) x 7.625 x 27 pF

Example with RS = 10 kOhm:
 (10000 + 2000) x 7.625 x 27*10-9 = 2.47µsec.

With DCO = 8 MHz and ADC clock divider = 3
The ADC clock source is 8000000/3 = 2.67 MHz
One ADC clock tick = 1000000/2666666=0.375 µsec.
With a calculated minimum sample time of 2.47 µsec the minimal
sample & hold time should be set to: 2.47/.375 = 6.59 ADC10CLKs
We may select 00 = 04 ADC10 clocks
              01 = 08 ADC10 clocks  (this one satisfies)
              10 = 16 ADC10 clocks
              11 = 64 ADC10 clocks

When we change the ADC10 clock, the sample and hold selection
must be change too. Note that the ADC10 clock is maximal 6.3 MHz
with ADC10SR=0 and 1.5 MHz with ADC10SR=1

When using the temperature sensor, the sample period must be
greater than 30 µs.
ADC clock should be 8000000/4 = 2 MHz (clock tick = 0.5 µsec)
We must use a sample time of 64 ADC clocks = 32 µsec.
*)

: 9600B     ( -- )  \ Baudrate 9600B
    int-off
    0081 0061 *bis  \ UCA0CTL1  Uart use SMCLK
    0041 0062 c!    \ UCA0BR0   8 mhz, baudrate 9600
    0003 0063 c!    \ UCA0BR1   idem
    0004 0064 c!    \ UCAMCTL   modulation ucbrsx = 2
    0001 0061 *bic  \ UCA0CTL   enable USCI
    ;

: 38K4      ( -- )  \ Baudrate 38K4
    int-off
    00D0 0062 c!    \ UCA0BR0   8 mhz, baudrate 38400
    0000 0063 c!    \ UCA0BR1   idem
    0006 0064 c!    \ UCAMCTL   modulation ucbrsx = 3
    0001 0061 *bic  \ UCA0CTL   enable USCI
    ;


\ ADC on and sample & hold time at 8 ADC10 clocks
: SETUP-ADC ( -- )
    39 22 *bic                  \ P1.0, P1.3,4,5 are inputs
    30 27 *bis  30 21 *bis      \ P1.4,5 are inputs with pullup
\ P2.0 to P2.5 are positive on led outputs
    12 1B0 **bic                \ ADC10CTL0  Deactivate ADC & clear ENC
    10 1B0 **bis                \ ADC10CTL0  Activate ADC
    09 04A c!                   \ ADC10AE0   P1.0 & P1.3 are ADC in
    0010 1B0 ! ;                \ ADC10CTL0  T-sample 8 ADC10 clocks,
\   0110 1B0 ! ;                \ ADC10CTL0  T-sample 64 ADC10 clocks,
                                \            ADC on & Vref = VCC & VSS

: ADC       ( +n -- u )
    F000 and                    \ Mask ADC input channel selector
    02 1B0 **bic                \ ADC10CTL0  Clear ENC
    40 or 1B2 !                 \ ADC10CTL1  Select input, MCLK/3
    03 1B0 **bis                \ ADC10CTL0  Set ENC & ADC10SC
    begin 4 1B0 bit** until     \ ADC10CTL0  ADC10 ready?
    1B4 @ ;                     \ ADC10MEM   Read result

: LIPO          0000 adc ;      \ Read level at P1.0
: LDR           3000 adc ;      \ Read level at P1.3

: .LIPO         ( -- )          \ Show LiPo voltage in decimal
    base @ >r  decimal          \ Uses a 4-digit & space format
    lipo dm 10364 dm 10000 */   \ Convert ADC to voltage
    0 <# # # ch . hold # #>     \ Make string
    type space  r> base ! ;     \ And print it

shield ADC\  freeze


\ LEDS & switches

: S1?           10 20 bit* 0= ; \ True if S1 is pressed
: S2?           20 20 bit* 0= ; \ True if S2 is pressed

value FORWARD?
: >DIR<     ( -- )
    s1? if  -1 to forward?  then
    s2? if   0 to forward?  then ;

: FORWARD   ( -- )
    ldr 260 - C0 umin  20 umax
    6 0 do
        1 i lshift 29 c!  >dir<
        dup ms
    loop  drop ;

: BACKWARD  ( -- )
    ldr 260 - C0 umin  20 umax
    6 0 do
        1 5 i - lshift 29 c!  >dir<
        dup ms
    loop  drop ;

: LOOPLICHT ( -- )
    setup-adc  -1 to forward?
    begin
       forward? if  forward
       else    backward
       then
    key? until  0 29 c! ;

shield LEDS\  freeze

\ End
