************************************************************************** * * Title: LED Light Dimmer Loop * * Objective: CMPEN 472 Homework 4 * * Revision: V1.0 * * Date: Feb. 14, 2025 * * Programmer: Jacob McDonnell * * Company: The Pennsylvania State University * Department of Computer Science and Engineering * * Algorithm: Simple Parallel I/O use, time delay-loop, and PWM control * * Register Use: A to control LEDS initially and for Light Level * X to hold the counter in the loop. * * Memory Use: RAM Locations from $3000 for data, * RAM Locations from $3100 for program * * Input: Parameters hard-coded in the program - PORTB * Switch 1 at PORTB bit 0 * Switch 2 at PORTB bit 1 * Switch 3 at PORTB bit 2 * Switch 4 at PORTB bit 3 * * Output: LED 1 at PORTB bit 4 * LED 2 at PORTB bit 5 * LED 3 at PORTB bit 6 * LED 4 at PORTB bit 7 * * Observation: This program will decrease LED 4 from 100% to 0% in 400ms * and then increase LED 4 from 0% to 100% in 400ms. The program * will loop forever. * * Note: ON CSM-12C128 board, * Switch 1 is at PORTB bit 0, and * LED 4 is at PORTB bit 7. * * Comments: This program is developed and simulated using CodeWarrior * development software and targeted for Axion * Manufacturing's CSM-12C128 board running at 24MHz. * ************************************************************************** * Parameter Declearation Section * * Export Symbols xdef pgstart ; export 'pgstart' symbol absentry pgstart ; for assembly entry point * Symbols and Macros PORTA equ $0000 ; i/o port A addresses DDRA equ $0002 ; data direction register for PORTA PORTB equ $0001 ; i/o port B addresses DDRB equ $0003 ; data direction register for PORTB ************************************************************************** * Data Section: address used [ $3000 to $30FF ] RAM Memory * org $3000 ; Reserved RAM memory starting address ; for Data for CMPEN 472 class Counter dc.w $0036 ; X register count number for time Delay ; loop for 10 useconds ; The work to calculate this number is in ; the comments for the delay10usec subroutine. LEVEL dc.b $0005 ; Light Level that the LED should be * ************************************************************************** * Program Section: address used [ $3100 to $3FFF ] RAM Memory * org $3100 ; Program start address, in RAM pgstart lds #$3100 ; initialize the stack pointer ldaa #%11110001 ; LED 1,2,3,4 at PORTB bit 4,5,6,7 staa DDRB ; set PORTB bit 4,5,6,7 as output ldaa #%01010000 staa PORTB ; Turn on only LEDs 1 & 3 on PORTB mainLoop ldaa #100 ; load 100 into accumulator A decrease tbeq A,increase ; Test if A == 0, skip loop if so staa LEVEL ; store A in counter LEVEL jsr dimmer ; jump to dimmer subroutine jsr dimmer ; jump to dimmer subroutine jsr dimmer ; jump to dimmer subroutine jsr dimmer ; jump to dimmer subroutine deca ; decrement accumulator A by 1 bra decrease ; loop to decrease always increase cmpa #100 ; Compare A to 100 beq mainLoop ; Test if A == 100, jump to mainLoop staa LEVEL ; store A in counter LEVEL jsr dimmer ; jump to dimmer subroutine jsr dimmer ; jump to dimmer subroutine jsr dimmer ; jump to dimmer subroutine jsr dimmer ; jump to dimmer subroutine inca ; increment accumulator A by 1 bra increase ; loop to increase always ************************************************************************** * Subroutine Section: address used [ $3100 to $3FFF ] RAM Memory * ;************************************************************************* ; dimmer subroutine ; ; This subroutine will dim LED4 to a given level ; ; Input: Two 1 byte counters, ONN and OFF, for how many times ; LED4 should be on and off for. ; Output: LED4 dimmed to a given level, wasted cycles ; Registers in use: A accumulator to counter number of times looped ; Memory locations in use: Two bytes ONN and OFF used to dim the LED4 to a given level ; ; Comments: This subroutine requires delay10usec subroutine ; dimmer bset PORTB,%10000000 ; Turn LED4 on psha ; Save A to the stack ldaa LEVEL ; Load the light level into accumulator A onDelay tbeq A, skipToOff ; Test if A == 0, skip loop if so jsr delay10usec ; delay for 10 microseconds deca ; decrement accumulator A by 1 bra onDelay ; jump back to onDelay always skipToOff bclr PORTB,%10000000 ; Turn off LED4 ldaa #100 ; load 100 into accumulator A suba LEVEL ; Subtract LEVEL to get off count offDelay tbeq A,doneLoop ; Test if A == 0, skip loop if so jsr delay10usec ; delay 10 microseconds deca ; decrement accumulator A by 1 bra offDelay ; jump back to offDelay always doneLoop pula ; restore A from the stack rts ; return to caller ;************************************************************************* ; delay10usec subroutine ; ; This subroutine causes a 10 usec. delay ; ; Input: a 16bit count number in 'Counter' ; Output: time delay, cpu cycle wasted ; Registers in use: X register, as counter ; Memory locations in use: a 16bit input number at 'Counter' ; ; Comments: Code relies on counter being $39 to be exactly 10 usec work is below ; Given: freq = 24MHz = 24000000 sec = 10 usec = 0.00001 ; freq = cycles / seconds ; ; cycles = freq * seconds = 24000000Hz * 0.00001 = 240 ; ; This sub routine is 12 + 4 * 'Counter' cycles long, solving for 'Counter' ; the result is found to be 57. ; delay10usec pshx ; Save register x to the stack ldx Counter ; load counter into register x innerLoop dex ; decrement register x by 1 bne innerLoop ; loop while register x is not 0 pulx ; restore register x from the stack nop ; extra nop to make exactly 10 usec rts ; return to caller