(* 100 Hz interrupt routine for the noForth led badge

   It has 70 leds arranged as a 7 x 10 array, the highest bit of
   the picture array ia always high. The brightness of the display
   can be set in 15 steps from 1 to 16!!
   So every row may get a different pulsewidth, the frequency
   is balanced by calculate the time for the eleventh position.

   Uses register XX and YY exclusive for the SCAN interrupt!!
   xx = address register
   yy = offset register

   021 = P1OUT
   029 = P2OUT
   019 = P3OUT

   Divide 8.000.000/2 = 4 MHz
   So the timer-0 clock input pulse is .250 microsec.

   FEDCBA9876543210 bit-nummers
   0000001001010100 CONSTANT #CONFIG \ TA is zero, count up, SMCLK, presc. /2

   To add:  USCII EEPROM I2C routines.
            EEPROM movie compiler.
            5x7 ASCII character set
*)

decimal
88 constant #PICT               \ Display buffer length
create BRIGHT  11 cells allot   \ Column brightness (PWM value)
create COPY    10 allot         \ Display buffer copy
create PICTURE #pict allot      \ Display buffer, byte 11 is a dummy

: SET-PAUSE     ( -- )          \ Calculate pause duration
    40000  10 0 do              \ Start with cycle duration
        i cells bright + @  -   \ Subtract brightness
    loop
    250 + bright 10 cells + ! ; \ Add minimal pause of 500 cycles

: >BRIGHT)      ( +n row -- )   \ Set brightness of single row
    cells >r  15 umin 1+  250 *  bright r> +  ! ;

: >BRIGHT       ( +n row -- )   \ Set brightness of a single row
    >bright) set-pause ;

: WHOLE         ( +n -- )       \ Set brightness for the whole screen
    10 0 do  dup i >bright)  loop  drop  set-pause ;

: >PICTURE      ( addr -- )     \ Copy picture from mem. address to display
    10 0 do
        i + c@ 80 or  picture i + c!
    loop
    drop ;

value DELAY                     \ Frame hold time
: FRAME         ( -- )      delay ms ;

(* Picture and movies from EEPROM

: EE>PICTURE    ( eeaddr -- )   \ Copy picture from EE address to display
    10 0 do
        i + ec@ 80 or  picture i + c!
    loop
    drop ;

\ Note that the first cell of a movie must contain the
\ full length of the stored picture frames in bytes!!
: EEMOVIE       ( eeaddr -- )   \ Play movie from EEPROM
    @+ bounds ?do               \ Get length of movie
        i ee>picture  frame     \ Play one frame at a time
    dm 10 +loop ;               \ To next picture

*)

hex
code SETUP-SCAN ( -- )
    #0 yy mov                   \ Init. offset register
    #0 160 & mov                \ Stop timer-A0
    dm 250 # 172 & mov          \ Interrupt after 500 cycles
    0254 # 160 & mov            \ Start timer
    10 # 162 & bis              \ Compare 0 interrupt on
    #8 sr bis                   \ General interrupts on
    next
end-code

routine SCAN    ( -- addr )
    picture # xx mov            \ Address of picture buffer
    yy xx add  xx ) 029 & .b mov
    bright # xx mov             \ Address of column brightness
    yy xx add  yy xx add  xx ) 172 & mov  ( TA0CCR0 )
    #0 yy cmp  =? if,           \ P3.6 active
        40 # 019 & .b bic
        #1 yy add  reti
    then,
    #1 yy cmp  =? if,           \ P1.3 active
        40 # 019 & .b bis
        #8 021 & .b bic
        #1 yy add  reti
    then,
    #2 yy cmp  =? if,           \ P1.4 active
        #8 021 & .b bis
        10 # 021 & .b bic
        #1 yy add  reti
    then,
    03 # yy cmp  =? if,         \ P1.5 active
        10 # 021 & .b bis
        20 # 021 & .b bic
        #1 yy add  reti
    then,
    #4 yy cmp  =? if,           \ P3.1 active
        20 # 021 & .b bis
        #2 019 & .b bic
        #1 yy add  reti
    then,
    05 # yy cmp  =? if,         \ P3.0 active
        #2 019 & .b bis
        #1 019 & .b bic
        #1 yy add  reti
    then,
    06 # yy cmp  =? if,         \ P3.2 active
        #1 019 & .b bis
        #4 019 & .b bic
        #1 yy add  reti
    then,
    07 # yy cmp  =? if,         \ P3.3 active
        #4 019 & .b bis
        #8 019 & .b bic
        #1 yy add  reti
    then,
    #8 yy cmp  =? if,           \ P3.4 active
        #8 019 & .b bis
        10 # 019 & .b bic
        #1 yy add  reti
    then,
    09 # yy cmp  =? if,         \ P3.5 active
        10 # 019 & .b bis
        20 # 019 & .b bic
        #1 yy add  reti
    then,
    20 # 019 & .b bis           \ Pause
    #0 yy mov  reti
end-code


\ Display tools

code UP     ( b1 -- b2 )        \ Variant of 2* with bit-7 always set
    7F # tos and>               \ Leave only low 7 bits
    40 # tos bit                \ Bit-6 to carry
    tos tos addc                \ Shift left using carry
    80 # tos bis                \ Bit-7 always high
    next
end-code

code DWN    ( b1 -- b2 )        \ Variant of 2/ with bit-7 always set
    7F # tos and>               \ Leave only low 7 bits
    tos rra  cs? if,            \ Shift right, bit-0 set?
        40 # tos bis            \ Yes, set bit-6
    then,
    80 # tos bis                \ Bit-7 always high
    next
end-code


: <<    ( +n -- )               \ Shift entire buffer +n positions left
    >r  picture copy r@ move
    picture r@ +  picture  #pict r@ - move
    copy picture #pict + r@ - r> move ;

: >>    ( +n -- )               \ Shift entire buffer +n positions right
    >r  picture #pict + r@ - copy r@ move
    picture dup r@ +  #pict r@ - move
    copy picture r> move ;

: /\    ( -- )                  \ Rotate entire picture one row up
    picture #pict bounds do
        i c@  up  i c!
    loop ;

: \/    ( -- )
    picture #pict bounds do     \ Rotate entire picture one row down
        i c@   dwn  i c!
    loop ;

scan  FFF2  vec!                \ Install timer-A0 vector
freeze

\ End

