; 8 channel PWM test program. ; ; Board: SX Demo/Proto Board ; ; 8 LEDs are fed with PWM signal. Each channel starts from a different value ; (0, 32, 64, 96, 128, 160, 192, 224) and goes slowly up and down. ; ; PWM code is based on Scott Dattalo's code. DEVICE SX28L, OSC4MHZ, TURBO, STACKX, OPTIONX RESET start ORG $08 ;global bank temp DS 1 ;short term temp dir DS 1 ;direction of PWM inputs change (inverted on reaching ;maximum (255) or minimum (1)). each bit is related to a PWM channel pwm_state DS 1 ;pwm outputs state (0 - off, 1 - on) pwm_period DS 1 ;pwm period counter ORG $10 ;bank0 pwm_bank EQU $ pwm0 DS 1 ;PWM counters pwm1 DS 1 pwm2 DS 1 pwm3 DS 1 pwm4 DS 1 pwm5 DS 1 pwm6 DS 1 pwm7 DS 1 ORG $30 ;bank1 ORG $50 ;bank2 ORG $70 ;bank3 ORG $90 ;bank4 ORG $B0 ;bank5 ORG $E0 ;bank6 ORG $F0 ;bank7 RA_DIR EQU %00000000 RB_DIR EQU %00000000 ;RB.0 .. RB.7 - LED outputs RC_DIR EQU %00000000 ORG $000 start ;init ports clr RA clr RB clr RC mov w, #RA_DIR mov !RA, w mov w, #RB_DIR mov !RB, w mov w, #RC_DIR mov !RC, w ;init vars call init_pwms ;**************************************************************************** ;pwm loop: ;**************************************************************************** bank pwm_bank pwm_loop clr w ;clear w, and then set bits of those ;channels that don't need to be reset decsz pwm0 ;don't set bit on reaching the end of a pwm pulse or w, #$01 decsz pwm1 or w, #$02 decsz pwm2 or w, #$04 decsz pwm3 or w, #$08 decsz pwm4 or w, #$10 decsz pwm5 or w, #$20 decsz pwm6 or w, #$40 decsz pwm7 or w, #$80 and w, pwm_state ;clear those bits that are zero already dec pwm_period ;decrement master pwm counter snz ;on reaching 0, set all outputs xor w, #$FF mov pwm_state, w ;update state ; and w, #$7F ;mask beeper on RB.7 mov RB, w ;update outputs ;on zero pwm_period counter update pwm counters ; ;Note: for a completely stable step size, a delay ; equal to update_pwms routine should be added ; on non-zero pwm_period. Can also be done using RTC. test pwm_period snz call update_pwms jmp pwm_loop ;**************************************************************************** ;Load PWM counters and inputs with 0, 32, 64, 96, 128, 160, 192, 224 init_pwms mov w, #pwm_bank ;use FSR as pointer mov FSR, w clr temp ;temp holds value and also is used as a counter inc temp init_pwms_loop mov w, temp ;load value mov IND, w ;save to pwm counter inc FSR ;next pwm channel mov w, #32 ;next value add temp, w sc ;loop until overflow jmp init_pwms_loop clr pwm_state ;initially all outputs are OFF clr pwm_period ;reset pwm counter clr dir ;init direction (all up) retp ;**************************************************************************** ;To each pwm channel counter: ;1) if direction=0, add 1. On reaching 255, change direction ;2) if direction=1, subtract 1. On reaching 1, change direction update_pwms mov w, #pwm_bank ;use FSR as pointer mov FSR, w mov w, #$80 ;temp holds direction value and also is used as a counter mov temp, w update_pwms_loop ;update pwm input according to direction mov w, #$01 ;w = dir == 0? 1 : 255 snb dir.0 mov w, #$FF add IND, w ;check limits add w, IND ;zero if the limit is reached mov w, #$01 ;invert the direction bit on borrow snz xor dir, w ;select next channel inc FSR rr dir ;shift new dir bit in temp rr temp ;and temp to carry (carry is set after 8 shifts) sc ;loop until overflow jmp update_pwms_loop ;update direction mov w, temp mov dir, w retp ;**************************************************************************** ORG $200 ORG $400 ORG $600