; Another Art Sobel Beep Oscillator ; Infrared Theremin ; ; Device ; device sx28L device turbo,STACKX_OPTIONX freq 50_000_000 id 'Theremin' reset reset_entry ; ; ; Equates ; adc0_out_pin = rc.0 adc0_in_pin = rc.1 adc1_out_pin = rc.2 adc1_in_pin = rc.3 pwm0_pin = rc.4 pwm1_pin = rc.6 ; ; ; Variables ; org 8 temp ds 1 byte ds 1 cmd ds 1 number_low ds 1 number_high ds 1 arg ds 1 string ds 1 table_add ds 1 org 0 org 10h ;bank0 variables timers = $ ;timer timer_high ds 1 timer_accl ds 1 timer_acch ds 1 freq_low ds 1 ;freq freq_high ds 1 freq_accl ds 1 freq_acch ds 1 org 30h ;bank1 variables analog = $ port_buff ds 1 ;buffer - used by all pwm0 ds 1 ;pwm0 pwm0_acc ds 1 pwm1 ds 1 ;pwm1 pwm1_acc ds 1 adc0 ds 1 ;adc0 adc0_count ds 1 adc0_acc ds 1 adc1 ds 1 ;adc1 adc1_count ds 1 adc1_acc ds 1 sin ds 1 sinacclo ds 1 sinacchi ds 1 sin_freq ds 1 org 50h ;bank2 variables org 0 ; ; ; Interrupt routine - virtual peripherals ; interrupt bank analog ;1 clr port_buff ;1 add pwm0_acc,pwm0 ;2 ;pwm0 snc ;1 setb port_buff.4 ;1 =4 add pwm1_acc,pwm1 ;2 ;pwm1 snc ;1 setb port_buff.6 ;1 =4 mov w,>>rc ;1 ;adc0/adc1 not w ;1 ;complement inputs to outputs and w,#%00000101 ;1 or port_buff,w ;1 =4 mov rc,port_buff ;2 =2 ;update port pins sb port_buff.0 ;1 ;adc0 inc adc0_acc ;1 ;if was high, inc acc mov w,adc0_acc ;1 ;get acc into w inc adc0_count ;1 ;done? snz ;1 ;if so, update adc0 mov adc0,w ;1 snz ;1 ;if so, reset acc clr adc0_acc ;1 =8 sb port_buff.2 ;1 ;adc1 inc adc1_acc ;1 ;if was high, inc acc mov w,adc1_acc ;1 ;get acc into w inc adc1_count ;1 ;done? snz ;1 ;if so, update adc0 mov adc1,w ;1 snz ;1 ;if so, reset acc clr adc1_acc ;1 =8 ;csa adc0, #10 ;mov adc0, #0 mov sin_freq, adc0 ;sine generation code add sinacclo, sin_freq ;2 ;advance sine at frequency addb sinacchi,c clc mov arg, sinacchi setb arg.0 mov w,>>arg ; and w,#$1f add w,table_add ;1 mov m,#0 iread ;get table entry mov m,#$F mov sin,w ;1 ; sin value snb arg.6 ;1 ;check bit 4 if set then negate sin value jmp :noinvert not sin ;dec sin ;1 ;complete invert operation :noinvert add sin,#128 ; add 128 to put it in the center of the PWM output mov rb,sin ; write the value of SIN into the output reg b ;mov rb,adc0 :intdone ;mov w,#-163 ;1 ;interrupt after 163 clocks ;retiw ;3 reti ;interrupt after 256 cycles ; ; ; Data ; sine table _table dw 00,12,25,37,49,60,71,81,91,99,106, 113,118, 122, 126, 127 dw 127, 126, 122, 118, 113, 106, 99, 91, 81, 71, 60, 49, 37, 25, 12 ; ;*************** ;* Subroutines * ;*************** ; ; ; ; ;******** ;* Main * ;******** ; ; ; Reset entry ; reset_entry ;mode reg=F mov ra,#%1111 ;init ra mov !ra,#%0000 mov rb,#%10000000 ;init rb mov !rb,#%00000000 ;all outputs clr rc ;init rc mov !rc,#%10101010 mov m,#$D ;set cmos input levels mov !rc,#0 mov m,#$F clr fsr ;reset all ram banks :loop setb fsr.4 clr ind ijnz fsr,:loop bank analog mov sin,#0 ;init variables. mov pwm0,#128 mov pwm1,#128 mov sin_freq,#255 mov table_add,#_table mov !option,#%10011111 ;enable rtcc interrupt ; bloop ;add sin,#1 ;mov rc,sin ;mov rb, sin jmp bloop ;do nothing (interrupts will handle the rest)