Assignment 2
Lucas Henry
V00962657
lucasleroyhenry@gmail.com
Q1:
The code for this question as well as Q2 uses the file regs_types.h, which includes various typedefs
and register names. It is shown below.
#include <stdint.h>
typedef volatile uint8_t* reg_ptr;
typedef volatile uint32_t* long_reg_ptr;
const reg_ptr PAIN = (reg_ptr)0xFFFFFFF0;
const reg_ptr PAOUT = (reg_ptr)0xFFFFFFF1;
const reg_ptr PADIR = (reg_ptr)0xFFFFFFF2;
const reg_ptr PBIN = (reg_ptr)0xFFFFFFF3;
const reg_ptr PBOUT = (reg_ptr)0xFFFFFFF4;
const reg_ptr PBDIR = (reg_ptr)0xFFFFFFF5;
const reg_ptr PSTAT = (reg_ptr)0xFFFFFFF6;
const reg_ptr PCONT = (reg_ptr)0xFFFFFFF7;
const reg_ptr IVECT = (reg_ptr)0x00000020;
const long_reg_ptr CNTM = (long_reg_ptr)0xFFFFFFD0;
const long_reg_ptr COUNT = (long_reg_ptr)0xFFFFFFD4;
const reg_ptr CTCON = (reg_ptr)0xFFFFFFD8;
const reg_ptr CTSTAT = (reg_ptr)0xFFFFFFD9;
The program for question 1 is shown below with comments.
#include "regs_types.h"
void isr(); // forward decl
uint8_t led1_active;
uint8_t val1, val2;
uint8_t btn_val() {
return *PBIN & 0x01;
}
void set_dig1(uint8_t val) {
*PBOUT = ((val % 10) << 4) | (*PBOUT & 0x0F);
}
void set_dig2(uint8_t val) {
*PAOUT = (val % 10) | (*PAOUT & 0xF0);
}
void set_leds(uint8_t led_1, uint8_t led_2) {
led_1 = led_1 == 0;
led_2 = led_2 == 0;
*PAOUT = (led_1 << 6) | (led_2 << 5) | (*PAOUT & 0x0F);
}
uint8_t decr_val(uint8_t val) {
if (val == 0) return 9;
return val - 1;
}
int main() {
*IVECT = (reg_ptr)&isr; // attach ISR
asm("MoveControl PSR, 0x40"); // enable interrupts
*PBDIR = 0xF0; // set first four to output, rest to input
*PBOUT = 0x00;
*PADIR = 0xFF; // set all to output
*PAOUT = 0x00;
*PBOUT = 0x00;
*CTCON |= 0x2; // stop timer
*CNTM = 100000000; // 100MHz, period of 1s -> CNTM should be 100_000_000
*CTCON = 0x91; // timer/counter set to timer, interrupts enabled, running
*CTCON |= 0x01;
led1_active = 1;
while (1) {
if (btn_val() != 0) continue;
while (btn_val() == 0);
led1_active = !led1_active;
set_leds(led1_active, !led1_active);
}
return 0;
}
void isr() {
if (*CTSTAT & 0x01 != 1) return;
*CTSTAT = 0x0; // unset flag
if (led1_active) {
val1 = decr_val(val1);
set_dig1(val1);
} else {
val2 = decr_val(val2);
set_dig2(val2);
}
}
Q2:
#include "regs_types.h"
void isr(); // forward decl
uint8_t led1_active;
uint8_t val1, val2;
#define T_ZERO (*CTSTAT & 0x01)
uint8_t btn_val() {
return *PAIN & 0x80;
}
void set_dig1(uint8_t val) {
*PAOUT = ((val % 10) << 3) | (*PAOUT & 0x87);
}
void set_dig2(uint8_t val) {
*PBOUT = ((val % 10) << 4) | (*PBOUT & 0x0F);
}
void set_leds(uint8_t led_1, uint8_t led_2) {
led_1 = led_1 == 0;
led_2 = led_2 == 0;
*PAOUT = (led_1 << 2) | led_2 | (*PAOUT & 0xF0);
}
uint8_t incr_val(uint8_t val) {
if (val == 9) return 0;
return val + 1;
}
int main() {
*IVECT = (reg_ptr)&isr; // attach ISR
asm("MoveControl PSR, 0x40"); // enable interrupts
*PBDIR = 0xFF; // all as output
*PBOUT = 0x00;
*PADIR = 0x7F; // bit 7 as input, all else as output
*PAOUT = 0x00;
*CTCON |= 0x2; // stop timer
*CNTM = 100000000; // 100MHz, period of 1s -> CNTM should be 100_000_000
*CTCON = 0x81; // timer/counter set to timer, running
*CTCON |= 0x01; // start timer
led1_active = 1;
while (1) {
while (!T_ZERO); // wait until you reach the bottom
*CTSTAT = 0x0; // clear status bit
if (led1_active) { // either increment dig1 or dig2
val1 = incr_val(val1);
set_dig1(val1);
} else {
val2 = incr_val(val2);
set_dig2(val2);
}
}
return 0;
}
void isr() {
if (*PSTAT & 0x40 != 1) return; // not an interrupt generated by PB
if (btn_val() == 0) return; // falling edge (start of press with pull-up)
led1_active = !led1_active; // toggle active led
set_leds(led1_active, !led1_active); // set both leds
}
Q3: