( 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