( ollie )
( daniel j kruszyna )
( http://krue.net/ollie/ )
( 2006.06.19 )

decimal
16000000 constant freq

hex

( hardware description )

( porta: r2r )

( portb.0: di )
( portb.1: do )
( portb.2: sck )
( portb.3: mcp2515 enable )
( portb.4: clock )
( portb.5: mcp41xxx enable )
( portb.6: mcp2515 interrupt )
( portb.7: reset )

( register defines )

1f constant zh
1e constant zl
1e constant zz
1d constant yh
1c constant yl
1c constant yy
1b constant xh
1a constant xl
1a constant xx
19 constant wh
18 constant wl
18 constant w

10 constant as

0e constant t5
0d constant t4
0c constant t3
0b constant t2
0a constant t1
09 constant t0

08 constant zero
07 constant inch
06 constant incm
05 constant incl
04 constant acch
03 constant accm
02 constant accl

include attiny26.f
include avr.f

1 evar node

1 var ticks
1 var note
1 var overtone

1 var multiplier
1 var divisor
1 var level
1 var velocity

portb 3 2constant mcp2515
portb 5 2constant mcp41xxx

: byte0 ff and ;
: byte1 8 >> byte0 ;
: byte2 10 >> byte0 ;
: byte3 18 >> byte0 ;
: 2load swap over byte0 load byte1 load ;

: 2ci, ( cl ch -- ) 08 << or i, ;
: >< dup ff00 and 8 >> swap 00ff and 8 << or ;
: stdid ( xx -- ) 07ff and 5 << >< i, 0000 i, ;

( sine wavetable )

label sine
80 83 2ci, 86 89 2ci, 8c 8f 2ci, 92 95 2ci,
98 9c 2ci, 9f a2 2ci, a5 a8 2ci, ab ae 2ci,
b0 b3 2ci, b6 b9 2ci, bc bf 2ci, c1 c4 2ci,
c7 c9 2ci, cc ce 2ci, d1 d3 2ci, d5 d8 2ci,
da dc 2ci, de e0 2ci, e2 e4 2ci, e6 e8 2ci,
ea ec 2ci, ed ef 2ci, f0 f2 2ci, f3 f5 2ci,
f6 f7 2ci, f8 f9 2ci, fa fb 2ci, fc fc 2ci,
fd fe 2ci, fe ff 2ci, ff ff 2ci, ff ff 2ci,
ff ff 2ci, ff ff 2ci, ff ff 2ci, fe fe 2ci,
fd fc 2ci, fc fb 2ci, fa f9 2ci, f8 f7 2ci,
f6 f5 2ci, f3 f2 2ci, f0 ef 2ci, ed ec 2ci,
ea e8 2ci, e6 e4 2ci, e2 e0 2ci, de dc 2ci,
da d8 2ci, d5 d3 2ci, d1 ce 2ci, cc c9 2ci,
c7 c4 2ci, c1 bf 2ci, bc b9 2ci, b6 b3 2ci,
b0 ae 2ci, ab a8 2ci, a5 a2 2ci, 9f 9c 2ci,
98 95 2ci, 92 8f 2ci, 8c 89 2ci, 86 83 2ci,
80 7c 2ci, 79 76 2ci, 73 70 2ci, 6d 6a 2ci,
67 63 2ci, 60 5d 2ci, 5a 57 2ci, 54 51 2ci,
4f 4c 2ci, 49 46 2ci, 43 40 2ci, 3e 3b 2ci,
38 36 2ci, 33 31 2ci, 2e 2c 2ci, 2a 27 2ci,
25 23 2ci, 21 1f 2ci, 1d 1b 2ci, 19 17 2ci,
15 13 2ci, 12 10 2ci, 0f 0d 2ci, 0c 0a 2ci,
09 08 2ci, 07 06 2ci, 05 04 2ci, 03 03 2ci,
02 01 2ci, 01 00 2ci, 00 00 2ci, 00 00 2ci,
00 00 2ci, 00 00 2ci, 00 00 2ci, 01 01 2ci,
02 03 2ci, 03 04 2ci, 05 06 2ci, 07 08 2ci,
09 0a 2ci, 0c 0d 2ci, 0f 10 2ci, 12 13 2ci,
15 17 2ci, 19 1b 2ci, 1d 1f 2ci, 21 23 2ci,
25 27 2ci, 2a 2c 2ci, 2e 31 2ci, 33 36 2ci,
38 3b 2ci, 3e 40 2ci, 43 46 2ci, 49 4c 2ci,
4f 51 2ci, 54 57 2ci, 5a 5d 2ci, 60 63 2ci,
67 6a 2ci, 6d 70 2ci, 73 76 2ci, 79 7c 2ci,

label wait
  wl 20 load
  do,
    wh ff load
    do,
      xl ff load
      do,
        nop, nop, nop, nop,
      xl loop,
    wh loop,
  wl loop,
  ret,

( usi spi driver )

( transfer one byte via spi )
label spi
  usidr wl store
  usisr usioif 2^ load
  wl usiwm0 2^ usics1 2^ or usiclk 2^ or usitc 2^ or load

  begin,
    usicr wl store
    usisr usioif skip-bit-set
  again,

  wl usidr fetch
  ret,

label spi
  usidr wl store
\  usisr usioif 2^ load
  as usiwm0 2^ usitc 2^ or load
  wl usiwm0 2^ usiclk 2^ or usitc 2^ or load

  usicr as store
  usicr wl store
  usicr as store
  usicr wl store
  usicr as store
  usicr wl store
  usicr as store
  usicr wl store
  usicr as store
  usicr wl store
  usicr as store
  usicr wl store
  usicr as store
  usicr wl store
  usicr as store
  usicr wl store

  wl usidr fetch
  ret,

include mcp2515.f

( amplitude envelope )

1 var env_state
2 var env_value
10 var env_data

label env_init
  env_state ff load
  xl env_value load
  zero stx+,
  zero stx+,
  zero stx+,
  zero stx+,
  zero stx+,
  zero stx+,
  zero stx+,
  zero stx+,
  zero stx+,
  zero stx+,
  zero stx+,
  zero stx+,
  zero stx+,
  zero stx+,
  zero stx+,
  zero stx+,
  zero stx+,
  zero stx+,
  ret,

\  env_value zero store
\  env_value 1 + zero store
\  env_data 0 + 40 load
\  env_data 1 + ff load
\  env_data 2 + 38 load
\  env_data 3 + d0 load
\  env_data 4 + 00 load
\  env_data 5 + c0 load
\  env_data 6 + 10 load
\  env_data 7 + 00 load
\  ret,

label env_tick
  wl env_state fetch
  wl ff cpi, z if, ( noteoff )
    ret,
  then,
 \  xh xl env_data 2load
  xl env_data load
  wl lsl,
  xl wl add,
 \  xh zero adc,
  t0 ldx+,
  t1 ldx+,
  t0 tst, z if, ( sustain )
    ret,
  then,
  t1 tst, z if, ( final )
    wl env_value fetch
    wh env_value 1 + fetch
    wl t0 sub,
    wh zero sbc,
    env_value wl store
    env_value 1 + wh store
    wh tst, z if, ( end )
      env_state ff load
\      incl clr, ( xxx )
\      incm clr, ( xxx )
\      inch clr, ( xxx )
\      accl 80 load ( xxx )
\      accm 80 load ( xxx )
\      acch 80 load ( xxx )
    then,
    ret,
  then,
  wl env_value fetch
  wh env_value 1 + fetch
  wh t1 cp, c if, ( level >= target )  
    wl t0 add,
    wh zero adc,
  else, ( level < target )
    wl t0 sub,
    wh zero sbc,
  then,
  env_value wl store
  env_value 1 + wh store
  wh t1 cp, z if, ( hit target )
    wl env_state fetch
    wl inc,
    env_state wl store
  then,
  ret,
  
label env_release
  xl env_data load
  wh clr,
  begin,
    wh inc,
    wl ldx+,
    xx 01 adiw,
  wl tst, z until,
  env_state wh store
\ env_state 03 load
\ env_value 1+ zero store
  ret,

label env_trigger
  env_state zero store
  ret,

\ label env_tick
\  ret,

\ label env_trigger
\  env_value 1 + ff load
\  ret,

\ label env_release
\  env_value 1 + 00 load
\  ret,

( eeprom )

( e[wl] -> wl )
label efetch
  begin,
    eecr eewe skip-bit-clear 
  again,
  eear wl store
  eecr eere set-bit
  wl eedr fetch
  ret,

label dca
  mcp41xxx clear-bit
  wl push,
  wl 11 load
  spi rcall,
  wl pop,
  spi rcall,
  mcp41xxx set-bit
  ret,
  
reset vector
  ( stack pointer )
  sp ramend load

  ( porta )
  ddra ff load

  ( portb )
  ddrb 2e load
  portb 28 load

  ( timer0 prescaler set to ck )
  tccr0 cs00 2^ load

  ( enable timer0 overflow interrupt )
  timsk toie0 2^ load

  ( set usi to three wire mode 0 )
  usicr 1a load

  ( external interrupt low level )
  gimsk int0 2^ load

  ( zero register )
  zero clr,

  ( initialize dco )
  accl clr,
  accm clr,
  acch clr,
  incl clr,
  incm clr,
  inch clr,

  ticks zero store
  level zero store
  velocity zero store

  wl 01 load
  multiplier wl store
  divisor wl store

  ( initialize dca )
\  wl node load
\  efetch rcall,
\  wh 04 load
\  wh wl sub,
\  wh lsl,
\  wh lsl,
\  wh lsl,
\  wh lsl,

\  wl wh mov,
\  level wl store

  wl 00 load
  dca rcall,
  
  can_reset rcall,
  can_init rcall,

  xh xl 07ff 2load
  wh rx_mask0 load
  can_setid rcall,

  xh xl 07ff 2load
  wh rx_mask1 load
  can_setid rcall,

\  xh xl 0400 2load
\  wh rx_filter0 load
\  can_setid rcall,

\  xh xl 0500 2load
\  wh rx_filter1 load
\  can_setid rcall,

  xh 07 load
  wl node load
  efetch rcall,
  xl wl mov,
  wh rx_filter2 load
  can_setid rcall,

  can_enable_output rcall,

  can_normal rcall,

\  ( xxx for now, harmonic is node + 1 )
\  wl node load
\  efetch rcall,
\  wl inc,
\  harmonic wl store

  env_init rcall,

  ( let's go )
  inton

  begin,
  again,

( wh * wl -> wh:wl )
( uses xh,xl )
label mul8
  xl 08 load
  xh wh mov,
  wh clr,
  do,
    clc,
    wl 0 skip-bit-clear
      wh xh add,
    wh ror,
    wl ror,
  xl loop,
  ret,

label control_tick
  inton
  wh push,
  t0 push,
  t1 push,
  xl push,
  xh push,
  
  env_tick call

  wh env_value 1 + fetch
\  wh envh mov,
  wl level fetch
  mul8 call
  wl velocity fetch
  mul8 call
  wl wh mov,
  intoff
  dca call
  inton

  xh pop,
  xl pop,
  t1 pop,
  t0 pop,
  wh pop,
  ret,

timer0_overflow vector
  pushsreg
  wl push,
  zl push,
  zh push,
  
  ( increment accumulator )
  accl incl add,
  accm incm adc,
  acch inch adc,

  ( get value from wavetable )
  zl sine 2* lo ldi,
  zh sine 2* hi ldi,
  zl acch add,
  zh zero adc,
  wl lpmz,

  ( output to dac )
  porta wl store

  wl ticks fetch
  wl inc,
  wl 0f andi,
  ticks wl store
  z if, control_tick call then,

  zh pop,
  zl pop,
  wl pop,
  popsreg
  reti,

label noteoff
  can_rx0 rcall,
  mcp2515 set-bit
\  level zero store
\  wl 00 load
\  dca rcall,
  env_release call

\  can_output0_off rcall,

  ret,

( xh:xl:wh:wl * t0 -> t4:t3:t2:t1:t0 )
( uses t5 )
label mul
  t1 clr,
  t2 clr,
  t3 clr,
  t4 clr,
  t5 08 load
  do,
    clc,
    t0 0 bst, t if,
      t1 wl add,
      t2 wh adc,
      t3 xl adc,
      t4 xh adc,
    then,
    t4 ror,
    t3 ror,
    t2 ror,
    t1 ror,
    t0 ror,
  t5 loop,
  ret,

( t4:t3:t2:t1:t0 / wl -> t4:t3:t2:t1:t0 )
label div
  wh 20 load
  do,
    t5 clr,
    t0 lsl,
    t1 rol,
    t2 rol,
    t3 rol,
    t4 rol,
    t5 rol,
    t4 wl cp,
    t5 zero cpc,
    c ~if,
      t0 inc,
      t4 wl sub,
\      t5 zero sbc,
    then,
  wh loop,
  ret,
  
label noteon
  can_rx0 rcall,
  spi rcall,
  xh wl mov,
  spi rcall,
  xl wl mov,
  spi rcall,
  wh wl mov,
  spi rcall,
  wl push,
  spi rcall,
  velocity wl store
  wl pop,
  mcp2515 set-bit

\  inton
  t0 push,
  t1 push,
  t2 push,
  t3 push,
  t4 push,
  t5 push,

  t0 multiplier fetch
  mul rcall,
  wl divisor fetch
  div rcall,

  incl t1 mov,
  incm t2 mov,
  inch t3 mov,

  t5 pop,
  t4 pop,
  t3 pop,
  t2 pop,
  t1 pop,
  t0 pop,
\  intoff

  ( xxx reset phase? )
\  accl clr,
\  accm clr,
\  acch clr,
  
  env_trigger call
\  level ff load
\ wl ff load
\  wl level fetch
\  dca rcall,

\  can_output0_on rcall,
  
  ret,

label nodeconfig
  can_rx1 rcall,
  spi rcall,
  note wl store
  spi rcall,
  overtone wl store
  mcp2515 set-bit

  can_config rcall,
  
  xh 02 load
  xl note fetch
  wh rx_filter0 load
  can_setid rcall,

  xh 03 load
  xl note fetch
  wh rx_filter1 load
  can_setid rcall,

  xh 06 load
  xl overtone fetch
  wh rx_filter3 load
  can_setid rcall,

  xh 05 load
  xl overtone fetch
  wh rx_filter4 load
  can_setid rcall,

  can_normal rcall,
  ret,

label overtoneconfig
  can_rx1 rcall,
  spi rcall,
  multiplier wl store
  spi rcall,
  divisor wl store
  spi rcall,
  level wl store
  mcp2515 set-bit
  ret,

label envconfig
  can_rx1 rcall,
  xl env_data load
  spi rcall,
  wl lsl,
  xl wl add,
  spi rcall,
  wl stx+,
  spi rcall,
  wl stx+,
  mcp2515 set-bit
  ret,

label can_event
  can_rxstatus rcall,
  wl 07 andi,
  wl 00 cpi, z if, noteoff rjmp, then,
  wl 01 cpi, z if, noteon rjmp, then,
  wl 02 cpi, z if, nodeconfig rjmp, then,
  wl 03 cpi, z if, overtoneconfig rjmp, then,
  wl 04 cpi, z if, envconfig rjmp, then,
  ret,
  
external_interrupt_0 vector
  pushsreg
  wl push,
  wh push,
  xl push,
  xh push,
\  can_output1_on rcall,
  can_event rcall,
\  can_output1_off rcall,
  xh pop,
  xl pop,
  wh pop,
  wl pop,
  popsreg
  reti,

s" flash" write-flash

