.( Compiling) cr d# 10 to eol ( newline ) [ifndef] purpose alias purpose: \ [then] defer get-msecs defer ms [ifndef] gpio-base \ From hwaddrs.fth \ Defined by MMP2 hardware h# d401.9000 constant gpio-base h# d405.1024 constant acgr-pa h# d401.5000 constant clock-unit-pa h# d405.0000 constant main-pmu-pa h# d428.2800 constant pmua-pa \ Application processor PMU register base h# d420.b800 constant dsi1-pa \ 4-lane controller h# d420.ba00 constant dsi2-pa \ 3-lane controller h# d420.b000 constant lcd-pa h# d401.4000 constant timer-pa [then] \ From timer.fth : +!@ ( value offset base -- ) + tuck l! l@ drop ; : timer! ( value offset -- ) timer-pa +!@ ; : init-timers ( -- ) h# 13 h# 24 clock-unit-pa + l! 0 h# 84 timer-pa + l! \ TMR_CER - count enable begin h# 84 timer-pa + l@ 7 and 0= until h# 24 h# 00 timer-pa +!@ \ TMR_CCR - clock control h# 200 0 do loop 0 h# 88 timer! \ count mode - periodic 0 h# 4c timer! \ preload value timer 0 0 h# 50 timer! \ preload value timer 1 0 h# 54 timer! \ preload value timer 2 0 h# 58 timer! \ free run timer 0 0 h# 5c timer! \ free run timer 1 0 h# 60 timer! \ free run timer 2 7 h# 74 timer! \ interrupt clear timer 0 h# 100 h# 4 timer! \ Force match h# 100 h# 8 timer! \ Force match h# 100 h# c timer! \ Force match h# 200 0 do loop 7 h# 84 timer! ; [ifdef] arm-assembler code timer0@ ( -- n ) \ 6.5 MHz psh tos,sp set r1,0xD4014000 mov r0,#1 str r0,[r1,#0xa4] mov r0,r0 ldr tos,[r1,#0x28] c; code timer1@ ( -- n ) \ 32.768 kHz psh tos,sp set r1,0xD4014000 mov r0,#1 str r0,[r1,#0xa8] mov r0,r0 ldr tos,[r1,#0x2c] c; code timer2@ ( -- n ) \ 1 kHz psh tos,sp set r1,0xD4014000 mov r0,#1 str r0,[r1,#0xac] mov r0,r0 ldr tos,[r1,#0x30] c; [else] : timer0@ ( -- n ) 1 h# d40140a4 l! h# d4014028 l@ ; : timer1@ ( -- n ) 1 h# d40140a8 l! h# d401402c l@ ; : timer2@ ( -- n ) 1 h# d40140ac l! h# d4014030 l@ ; [then] : timer0-status@ ( -- n ) h# d4014034 l@ ; : timer1-status@ ( -- n ) h# d4014038 l@ ; : timer2-status@ ( -- n ) h# d401403c l@ ; : timer0-ier@ ( -- n ) h# d4014040 l@ ; : timer1-ier@ ( -- n ) h# d4014044 l@ ; : timer2-ier@ ( -- n ) h# d4014048 l@ ; : timer0-icr! ( n -- ) h# d4014074 l! ; : timer1-icr! ( n -- ) h# d4014078 l! ; : timer2-icr! ( n -- ) h# d401407c l! ; : timer0-ier! ( n -- ) h# d4014040 l! ; : timer1-ier! ( n -- ) h# d4014044 l! ; : timer2-ier! ( n -- ) h# d4014048 l! ; : timer0-match0! ( n -- ) h# d4014004 l! ; : timer0-match0@ ( -- n ) h# d4014004 l@ ; : timer0-match1! ( n -- ) h# d4014008 l! ; : timer0-match1@ ( -- n ) h# d4014008 l@ ; : timer0-match2! ( n -- ) h# d401400c l! ; : timer0-match2@ ( -- n ) h# d401400c l@ ; : timer1-match0! ( n -- ) h# d4014010 l! ; : timer1-match0@ ( -- n ) h# d4014010 l@ ; : timer1-match1! ( n -- ) h# d4014014 l! ; : timer1-match1@ ( -- n ) h# d4014014 l@ ; : timer1-match2! ( n -- ) h# d4014018 l! ; : timer1-match2@ ( -- n ) h# d4014018 l@ ; : timer2-match0! ( n -- ) h# d401401c l! ; : timer2-match0@ ( -- n ) h# d401401c l@ ; : timer2-match1! ( n -- ) h# d4014020 l! ; : timer2-match1@ ( -- n ) h# d4014020 l@ ; : timer2-match2! ( n -- ) h# d4014024 l! ; : timer2-match2@ ( -- n ) h# d4014024 l@ ; ' timer2@ to get-msecs : (ms) ( delay-ms -- ) get-msecs + begin ( limit ) pause ( limit ) dup get-msecs - ( limit delta ) 0< until ( limit ) drop ; ' (ms) to ms : us ( delay-us -- ) d# 13 2 */ timer0@ + ( limit ) begin ( limit ) dup timer0@ - ( limit delta ) 0< until ( limit ) drop ; \ Timing tools variable timestamp : t-update ; : t( ( -- ) timer0@ timestamp ! ; : ))t ( -- ticks ) timer0@ timestamp @ - ; : ))t-usecs ( -- usecs ) ))t 2 d# 13 */ ; : )t ( -- ) ))t-usecs ( microseconds ) push-decimal <# u# u# u# [char] , hold u# u#s u#> type ." us " pop-base ; : t-msec( ( -- ) timer2@ timestamp ! ; : ))t-msec ( -- msecs ) timer2@ timestamp @ - ; : )t-msec ( -- ) ))t-msec push-decimal <# u# u#s u#> type ." ms " pop-base ; : t-sec( ( -- ) t-msec( ; : ))t-sec ( -- secs ) ))t-msec d# 1000 / ; : )t-sec ( -- ) ))t-sec push-decimal <# u# u#s u#> type ." s " pop-base ; : .hms ( seconds -- ) d# 60 /mod d# 60 /mod ( sec min hrs ) push-decimal <# u# u#s u#> type ." :" <# u# u# u#> type ." :" <# u# u# u#> type pop-base ; : t-hms( ( -- ) t-sec( ; : )t-hms ))t-sec ( seconds ) .hms ; \ From twsi.fth purpose: Driver for Two Wire Serial Interface on Marvell Armada 610 \ 0 0 " d4011000" " /" begin-package 0 value chip 0 value clock-reg 0 value slave-address : dbr@ ( -- n ) chip h# 08 + l@ ; : cr@ ( -- n ) chip h# 10 + l@ ; : sr@ ( -- n ) chip h# 18 + l@ ; : sar@ ( -- n ) chip h# 20 + l@ ; : lcr@ ( -- n ) chip h# 28 + l@ ; : dbr! ( n -- ) chip h# 08 + l! ; : cr! ( n -- ) chip h# 10 + l! ; : sr! ( n -- ) chip h# 18 + l! ; : sar! ( n -- ) chip h# 20 + l! ; : lcr! ( n -- ) chip h# 28 + l! ; create channel-bases h# D4011000 , h# D4031000 , h# D4032000 , h# D4033000 , h# D4033800 , h# D4034000 , create clock-offsets h# 04 c, h# 08 c, h# 0c c, h# 10 c, h# 7c c, h# 80 c, : set-twsi-channel ( channel -- ) 1- channel-bases over na+ @ to chip ( channel ) clock-offsets + c@ clock-unit-pa + to clock-reg ( ) ; : set-twsi-target ( slave channel -- ) \ Channel numbers range from 1 to 6 set-twsi-channel to slave-address ; \ Bit defines h# 4000 constant bbu_ICR_UR \ Unit Reset bit h# 0040 constant bbu_ICR_IUE \ ICR TWSI Unit enable bit h# 0020 constant bbu_ICR_SCLE \ ICR TWSI SCL Enable bit h# 0010 constant bbu_ICR_MA \ ICR Master Abort bit h# 0008 constant bbu_ICR_TB \ ICR Transfer Byte bit h# 0004 constant bbu_ICR_ACKNAK \ ICR ACK bit h# 0002 constant bbu_ICR_STOP \ ICR STOP bit h# 0001 constant bbu_ICR_START \ ICR START bit h# 0040 constant bbu_ISR_ITE \ ISR Transmit empty bit h# 0400 constant bbu_ISR_BED \ Bus Error Detect bit h# 1000 constant BBU_TWSI_TimeOut \ TWSI bus timeout loop counter value bbu_ICR_IUE bbu_ICR_SCLE or constant iue+scle : init-twsi-channel ( channel# -- ) set-twsi-channel 7 clock-reg l! 3 clock-reg l! \ Set then clear reset bit 1 us iue+scle bbu_ICR_UR or cr! \ Reset the unit iue+scle cr! \ Release the reset 0 sar! \ Set host slave address 0 cr! \ Disable interrupts ; : init-twsi ( -- ) 7 1 do i init-twsi-channel loop ; : twsi-run ( extra-flags -- ) iue+scle or bbu_ICR_TB or cr! ( ) h# 1000 0 do cr@ bbu_ICR_TB and 0= if unloop exit then loop true abort" TWSI timeout" ; : twsi-putbyte ( byte extra-flags -- ) swap dbr! ( extra-flags ) twsi-run ; : twsi-getbyte ( extra-flags -- byte ) twsi-run ( ) dbr@ ( byte ) sr@ sr! ( byte ) ; : twsi-start ( slave-address -- ) bbu_ICR_START twsi-putbyte ( ) sr@ bbu_ISR_BED and if ( ) bbu_ISR_BED sr! ( ) iue+scle bbu_ICR_MA or cr! ( ) true abort" TWSI bus error" then ( ) ; : twsi-get ( register-address .. #reg-bytes #data-bytes -- data-byte ... ) >r ( reg-adr .. #regs r: #data-bytes ) \ Handle the case where the device does not require that a write register address be sent slave-address ( reg-adr .. #regs slave-address r: #data-bytes ) over 0= if ( reg-adr .. #regs slave-address r: #data-bytes ) r@ if ( reg-adr .. #regs slave-address r: #data-bytes ) 1 or ( reg-adr .. #regs slave-address' r: #data-bytes ) then ( reg-adr .. #regs slave-address' r: #data-bytes ) then ( reg-adr .. #regs slave-address' r: #data-bytes ) twsi-start ( reg-adr .. #regs r: #data-bytes ) \ Abort the transaction if both #reg-bytes and #data-bytes are 0 dup r@ or 0= if ( #regs r: #data-bytes ) iue+scle bbu_ICR_MA or cr! ( #regs r: #data-bytes ) \ Master abort r> 2drop exit ( -- ) then ( reg-adr .. #regs r: #data-bytes ) \ Send register addresses, if any 0 ?do 0 twsi-putbyte loop ( r: #data-bytes ) \ If no result data requested, quit now r> dup 0= if ( #data-bytes ) drop ( ) iue+scle bbu_ICR_STOP or cr! ( ) exit then ( #data-bytes ) \ Otherwise send the read address with another start bit slave-address 1 or bbu_ICR_START twsi-putbyte ( #data-bytes ) sr@ sr! \ clear ITE and IRF status bits ( #data-bytes ) \ Bug on line 367 of bbu_TWSI.s - writes SR without first reading it 1- 0 ?do 0 twsi-getbyte loop ( bytes ) \ Set the stop bit on the final byte bbu_ICR_STOP bbu_ICR_ACKNAK or twsi-getbyte ( bytes ) ; : twsi-write ( byte .. #bytes -- ) slave-address twsi-start ( byte .. #bytes ) 1- 0 ?do 0 twsi-putbyte loop ( byte ) bbu_ICR_STOP twsi-putbyte ( ) ; : twsi-b@ ( reg -- byte ) 1 1 twsi-get ; : twsi-b! ( byte reg -- ) 2 twsi-write ; : init init-timers init-twsi ; .( Done) cr .( Type 'init' to run timer/twsi init routine.) cr