;sxdemo.src ; ; Device ; device pins28,pages1,banks8,oschs device turbo,stackx,optionx id 'SX Demo' reset reset_entry ; ; This code demonstrates the ability of the SX28AC to use software ; Virtual Peripherals to implement the following: ; 4 PWM outputs (RA0 - RA3) ; 6 UARTS (RB0-RB5, RC0-RC5) ; 4 16 bit TIMERS ; 2 8 bit A/D Converters (RB6-RB7, RC6-RC7) ; ; Equates ; ra_dir = %0000 pwm0_pin = ra.0 pwm1_pin = ra.1 pwm2_pin = ra.2 pwm3_pin = ra.3 rb_dir = %00111111 rx0_pin = rb.0 rx1_pin = rb.1 rx2_pin = rb.2 rx3_pin = rb.3 rx4_pin = rb.4 rx5_pin = rb.5 adc0_out_pin = rb.6 adc1_out_pin = rb.7 rc_dir = %11000000 tx0_pin = rc.0 tx1_pin = rc.1 tx2_pin = rc.2 tx3_pin = rc.3 tx4_pin = rc.4 tx5_pin = rc.5 adc0_in_pin = rc.6 adc1_in_pin = rc.7 ; ; ; Variables ; org 8 ;common-bank variables master_count ds 1 master_mask ds 1 itemp ds 1 rx_flags ds 1 rx0_full = rx_flags.0 rx1_full = rx_flags.1 rx2_full = rx_flags.2 rx3_full = rx_flags.3 rx4_full = rx_flags.4 rx5_full = rx_flags.5 org 10ドル ;bank0 variables timer_low ds 1 ;timer write buffer timer_high ds 1 timer_flags ds 1 timer0_flag = timer_flags.0 timer1_flag = timer_flags.1 timer2_flag = timer_flags.2 timer3_flag = timer_flags.3 org 30ドル ;bank1 variables timers = $ timer0_low ds 1 ;timer0 timer0_high ds 1 timer0_l ds 1 timer0_h ds 1 timer1_low ds 1 ;timer1 timer1_high ds 1 timer1_l ds 1 timer1_h ds 1 timer2_low ds 1 ;timer2 timer2_high ds 1 timer2_l ds 1 timer2_h ds 1 timer3_low ds 1 ;timer3 timer3_high ds 1 timer3_l ds 1 timer3_h ds 1 org 50ドル ;bank2 variables analog = $ pwm0 ds 1 ;pwm0 pwm0_acc ds 1 pwm1 ds 1 ;pwm1 pwm1_acc ds 1 pwm2 ds 1 ;pwm2 pwm2_acc ds 1 pwm3 ds 1 ;pwm3 pwm3_acc ds 1 adc0 ds 1 ;adc0 adc0_acc ds 1 adc0_count ds 1 adc1 ds 1 ;adc1 adc1_acc ds 1 adc1_count ds 1 org 70ドル ;bank3 variables serial_out = $ tx0_flag ds 1 ;tx0 tx0_data ds 1 tx1_flag ds 1 ;tx1 tx1_data ds 1 tx2_flag ds 1 ;tx2 tx2_data ds 1 tx3_flag ds 1 ;tx3 tx3_data ds 1 tx4_flag ds 1 ;tx4 tx4_data ds 1 tx5_flag ds 1 ;tx5 tx5_data ds 1 tx6_flag ds 1 ;tx6 tx6_data ds 1 tx7_flag ds 1 ;tx7 tx7_data ds 1 org 90ドル ;bank4 variables serial_in = $ rx0_flag ds 1 ;rx0 rx0_data ds 1 rx1_flag ds 1 ;rx1 rx1_data ds 1 rx2_flag ds 1 ;rx2 rx2_data ds 1 rx3_flag ds 1 ;rx3 rx3_data ds 1 rx4_flag ds 1 ;rx4 rx4_data ds 1 rx5_flag ds 1 ;rx5 rx5_data ds 1 rx6_flag ds 1 ;rx6 rx6_data ds 1 rx7_flag ds 1 ;rx7 rx7_data ds 1 org 0 jmp interrupt ; ; ;*************** ;* Subroutines * ;*************** ; ; ; Set up timer W [0-3] - timer_low and timer_high must hold value ; timer_setup not timer_low ;get swapped 2's complement of value not timer_high inc timer_low snz inc timer_high swap timer_low swap timer_high and w,#03ドル ;point fsr to timer [W] data clc rl wreg rl wreg or w,#timers mov fsr,w mov ind,timer_low ;init timer [W] inc fsr mov ind,timer_high inc fsr mov ind,#$FE inc fsr mov ind,#$FF ret ; ; ;******** ;* Main * ;******** ; ; Reset entry ; reset_entry clr ra ;init ra mov !ra,#ra_dir clr rb ;init rb mov !rb,#rb_dir clr rc ;init rc mov !rc,#rc_dir mov m,#$D ;set cmos input levels on rc mov !rc,#0 mov m,#$F mov fsr,#08ドル ;reset all ram registers :loop sb fsr.3 setb fsr.4 clr ind ijnz fsr,:loop mov master_mask,#01ドル ;init master_mask mov !option,#%00000000 ;enable rtcc interrupt ; ; ; User's program ; ; To setup timer, write value to timer_low and timer_high, ; load W with timer# (0-3), and call set_timer. the corresponding ; timerX_flag will be set. It must be reset in software. ; ; To set a pwm channel, write an 8-bit value to pwmX. ; ; To read an adc, simple read adcX. ; ; To output serial, wait for the particular txX_flag to contain 0, ; then write the byte to transmit to txX_data and write 10h to txX_flag. ; ; To input serial, check for an rxX_full flag set. Then get the ; byte from the associated rxX_data register. Clear the rxX_full ; flag afterwards. ; main bank analog ;select analog bank mov w,adc0 ;read adc mov pwm0,w ;write value to pwm bank serial_out ;select serial out bank test tx0_flag ;if tx0 is ready, output byte jnz :tx0_busy mov tx0_data,w mov tx0_flag,#10ドル :tx0_busy test tx1_flag ;if tx1 is ready, check rx0 jnz :tx1_busy jnb rx0_full,:tx1_busy ;if rx0 not full, skip bank serial_in ;select serial in bank mov w,rx0_data ;get byte received from rx0 bank serial_out ;select serial out bank mov tx1_data,w ;write byte to tx0 mov tx1_flag,#10ドル clrb rx0_full :tx1_busy jmp main ; ; ; Interrupt routine - virtual peripherals ; interrupt inc master_count ;1 ;update timing data mov w,<<master_mask ;1 rl master_mask ;1 bank timers ;1 ;timers inc timer0_l ;1 ;16-bit timer0 snz ;1 inc timer0_h ;1 mov w,<>timer0_low ;1 snz ;1 mov timer0_l,w ;1 mov w,<>timer0_high ;1 snz ;1 mov timer0_h,w ;1 snz ;1 setb timer0_flag ;1 =11 inc timer1_l ;1 ;16-bit timer1 snz ;1 inc timer1_h ;1 mov w,<>timer1_low ;1 snz ;1 mov timer1_l,w ;1 mov w,<>timer1_high ;1 snz ;1 mov timer1_h,w ;1 snz ;1 setb timer1_flag ;1 =11 inc timer2_l ;1 ;16-bit timer2 snz ;1 inc timer2_h ;1 mov w,<>timer2_low ;1 snz ;1 mov timer2_l,w ;1 mov w,<>timer2_high ;1 snz ;1 mov timer2_h,w ;1 snz ;1 setb timer2_flag ;1 =11 inc timer3_l ;1 ;16-bit timer3 snz ;1 inc timer3_h ;1 mov w,<>timer3_low ;1 snz ;1 mov timer3_l,w ;1 mov w,<>timer3_high ;1 snz ;1 mov timer3_h,w ;1 snz ;1 setb timer3_flag ;1 =11 bank analog ;1 ;pwm's and adc's clr itemp ;1 add pwm0_acc,pwm0 ;2 ;pwm0 snc ;1 setb itemp.0 ;1 =4 add pwm1_acc,pwm1 ;2 ;pwm1 snc ;1 setb itemp.1 ;1 =4 add pwm2_acc,pwm2 ;2 ;pwm2 snc ;1 setb itemp.2 ;1 =4 add pwm3_acc,pwm3 ;2 ;pwm3 snc ;1 setb itemp.3 ;1 =4 mov ra,itemp ;2 mov w,/rc ;1 ;adc0/adc1 mov rb,w ;1 ;complement inputs to outputs rl wreg ;1 ;get adc0 into w.7 and adc1 into c sb wreg.7 ;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 sc ;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 bank serial_out ;1 mov w,<<master_count;1 ;8 serial outputs and w,#0ドルE ;1 or w,#serial_out ;1 mov fsr,w ;1 mov w,rc ;1 or w,master_mask ;1 snb ind.7 ;1 xor w,master_mask ;1 mov rc,w ;1 test ind ;1 rl ind ;1 clc ;1 setb fsr.0 ;1 sz ;1 rr ind ;1 clrb fsr.0 ;1 rr ind ;1 sz ;1 dec ind ;1 =19 bank serial_in ;1 rx0 clc ;1 ;serial input snb rb.0 ;1 ;get rx pin into c stc ;1 mov w,#$F0 ;1 ;busy? and w,rx0_flag ;1 jnz :busy ;2,4 ;(jitter okay) jc :not ;2,3 ;start bit? mov w,#0ドルC ;1 ;got start add w,master_count ;1 ;set 1.5 bit delay and w,#0ドルF ;1 or w,#60ドル ;1 mov rx0_flag,w ;1 :busy mov w,rx0_flag ;1 ;busy, bit ready? xor w,master_count ;1 and w,#0ドルF ;1 jnz :not ;2,4 ;(jitter okay) mov w,rx0_flag ;1 ;if stop bit, don't save or w,#0ドルF ;1 incsz wreg ;1 rr rx0_data ;1 ;data bit, save add rx0_flag,#10ドル ;2 ;inc bit counter snc ;1 setb rx0_full ;1 ;if done, set flag xor rx0_flag,#08ドル ;1 ;set 1 bit delay :not rx1 clc ;1 ;serial input snb rb.0 ;1 ;get rx pin into c stc ;1 mov w,#$F0 ;1 ;busy? and w,rx1_flag ;1 jnz :busy ;2,4 ;(jitter okay) jc :not ;2,3 ;start bit? mov w,#0ドルC ;1 ;got start add w,master_count ;1 ;set 1.5 bit delay and w,#0ドルF ;1 or w,#60ドル ;1 mov rx1_flag,w ;1 :busy mov w,rx1_flag ;1 ;busy, bit ready? xor w,master_count ;1 and w,#0ドルF ;1 jnz :not ;2,4 ;(jitter okay) mov w,rx1_flag ;1 ;if stop bit, don't save or w,#0ドルF ;1 incsz wreg ;1 rr rx1_data ;1 ;data bit, save add rx1_flag,#10ドル ;2 ;inc bit counter snc ;1 setb rx1_full ;1 ;if done, set flag xor rx1_flag,#08ドル ;1 ;set 1 bit delay :not rx2 clc ;1 ;serial input snb rb.0 ;1 ;get rx pin into c stc ;1 mov w,#$F0 ;1 ;busy? and w,rx2_flag ;1 jnz :busy ;2,4 ;(jitter okay) jc :not ;2,3 ;start bit? mov w,#0ドルC ;1 ;got start add w,master_count ;1 ;set 1.5 bit delay and w,#0ドルF ;1 or w,#60ドル ;1 mov rx2_flag,w ;1 :busy mov w,rx2_flag ;1 ;busy, bit ready? xor w,master_count ;1 and w,#0ドルF ;1 jnz :not ;2,4 ;(jitter okay) mov w,rx2_flag ;1 ;if stop bit, don't save or w,#0ドルF ;1 incsz wreg ;1 rr rx2_data ;1 ;data bit, save add rx2_flag,#10ドル ;2 ;inc bit counter snc ;1 setb rx2_full ;1 ;if done, set flag xor rx2_flag,#08ドル ;1 ;set 1 bit delay :not rx3 clc ;1 ;serial input snb rb.0 ;1 ;get rx pin into c stc ;1 mov w,#$F0 ;1 ;busy? and w,rx3_flag ;1 jnz :busy ;2,4 ;(jitter okay) jc :not ;2,3 ;start bit? mov w,#0ドルC ;1 ;got start add w,master_count ;1 ;set 1.5 bit delay and w,#0ドルF ;1 or w,#60ドル ;1 mov rx3_flag,w ;1 :busy mov w,rx3_flag ;1 ;busy, bit ready? xor w,master_count ;1 and w,#0ドルF ;1 jnz :not ;2,4 ;(jitter okay) mov w,rx3_flag ;1 ;if stop bit, don't save or w,#0ドルF ;1 incsz wreg ;1 rr rx3_data ;1 ;data bit, save add rx3_flag,#10ドル ;2 ;inc bit counter snc ;1 setb rx3_full ;1 ;if done, set flag xor rx3_flag,#08ドル ;1 ;set 1 bit delay :not rx4 clc ;1 ;serial input snb rb.0 ;1 ;get rx pin into c stc ;1 mov w,#$F0 ;1 ;busy? and w,rx4_flag ;1 jnz :busy ;2,4 ;(jitter okay) jc :not ;2,3 ;start bit? mov w,#0ドルC ;1 ;got start add w,master_count ;1 ;set 1.5 bit delay and w,#0ドルF ;1 or w,#60ドル ;1 mov rx4_flag,w ;1 :busy mov w,rx4_flag ;1 ;busy, bit ready? xor w,master_count ;1 and w,#0ドルF ;1 jnz :not ;2,4 ;(jitter okay) mov w,rx4_flag ;1 ;if stop bit, don't save or w,#0ドルF ;1 incsz wreg ;1 rr rx4_data ;1 ;data bit, save add rx4_flag,#10ドル ;2 ;inc bit counter snc ;1 setb rx4_full ;1 ;if done, set flag xor rx4_flag,#08ドル ;1 ;set 1 bit delay :not rx5 clc ;1 ;serial input snb rb.5 ;1 ;get rx pin into c stc ;1 mov w,#$F0 ;1 ;busy? and w,rx5_flag ;1 jnz :busy ;2,4 ;(jitter okay) jc :not ;2,3 ;start bit? mov w,#0ドルC ;1 ;got start add w,master_count ;1 ;set 1.5 bit delay and w,#0ドルF ;1 or w,#60ドル ;1 mov rx5_flag,w ;1 :busy mov w,rx5_flag ;1 ;busy, bit ready? xor w,master_count ;1 and w,#0ドルF ;1 jnz :not ;2,4 ;(jitter okay) mov w,rx5_flag ;1 ;if stop bit, don't save or w,#0ドルF ;1 incsz wreg ;1 rr rx5_data ;1 ;data bit, save add rx5_flag,#10ドル ;2 ;inc bit counter snc ;1 setb rx5_full ;1 ;if done, set flag xor rx5_flag,#08ドル ;1 ;set 1 bit delay :not mov w,#-163 ;1 ;interrupt every 163*2 clocks retiw ;3 ;(2 is from prescaler, rate=8*19.2KHz)
.