#include <avr/io.
h> // Include register definitions
.section .init0 // Places code at the top of programme memory
.include "include/buzzer.S" // Configures TCA0 to drive buzzer
entry:
// Ex 3.0
//
// In Ex 3.1 we are going to enable PB5 as an output, which is
// connected to the DISP DP net and controls LED DS1-DP (active low).
//
// Write assembly code such that when we enable PB5 as an output,
// LED DS1-DP is off.
ldi r16, PIN5_bm //0b0010 0000
sts PORTB_OUTSET, r16
// Write your code for Ex 3.0 above this line.
// Ex 3.1
//
// Write assembly code to enable the pin connected to the DISP DP
// net as an output.
ldi r16, PIN5_bm //0b0010 0000
sts PORTB_DIR, r16
// Write your code for Ex 3.1 above this line.
// Ex 3.2
//
// In later exercises you will be required to read the state of
// pushbuttons BUTTON0...3. Write assembly code to enable the
// internal pull-up resistors for the pins connected to these
// pushbuttons.
ldi r16, PORT_PULLUPEN_bm // enable pull-up bitmask
sts PORTA_PIN4CTRL, r16
sts PORTA_PIN5CTRL, r16
sts PORTA_PIN6CTRL, r16
sts PORTA_PIN7CTRL, r16
// Write your code for Ex 3.2 above this line.
// Ex 3.3
//
// Write assembly code to turn on LED DS1-DP.
ldi r16, PIN5_bm
sts PORTB_OUTCLR, r16 // set low (turn LED on)
// Write your code for Ex 3.3 above this line.
// The code between the "loop_100ms" and "end_loop_100ms" labels
// will execute approximately 10 times per second.
loop_100ms:
// Ex 3.4
//
// Write assembly code to read the state of BUTTON0 and store the result in
R17.
// If BUTTON0 is pressed:
// R17 should contain the value 0x00.
// Else, if BUTTON0 is not pressed (released):
// R17 should contain a non-zero value.
//
// Hint: You can use a bitmask and bitwise logical operation to
// isolate the bit that corresponds to the relevant pushbutton
// after reading the port state.
//ldi r16, 0b00010000 ; Load binary value 00000001 into register r16
lds r17, PORTA_IN ; Check BUTTON0 and store the result in r17
andi r17,0b00010000 ; r17 = 0 if Button 0 Pressed
// Write your code for Ex 3.4 above this line.
// Ex 3.5
//
// The two instructions below will test the value in R17 to determine
// whether BUTTON0 is pressed.
//
// If BUTTON0 is NOT pressed (i.e., the value in R17 is not zero),
// any code between the "brne" instruction and the label "end_loop_100ms"
// will be skipped.
//
// Write assembly code in the space provided to toggle the state of LED DS1-
DP.
cpi r17, 0
brne end_loop_100ms
// Write your code for Ex 3.5 below this line.
ldi r16, PIN5_bm //0b00010000 ; Load binary value 00000010 into register
r16
sts PORTB_OUTTGL, r16
// Write your code for Ex 3.5 above this line.
end_loop_100ms:
// The code between the "loop_10ms" and "end_loop_10ms" labels
// will execute approximately 100 times per second.
loop_10ms:
// Ex 3.6
//
// At the start of this programme, some code was included that sets up
// the Timer Counter A 0 (TCA0) peripheral to synthesize a ~200 Hz tone
// that will drive the piezo buzzer connected to the BUZZER net.
//
// TCA0 will automatically override the output of the pin connected
// to the BUZZER net, however, the pin needs to be configured as an output
// for the timer signal to define the state of the BUZZER net.
//
// Write assembly code below such that the buzzer is driven
// (i.e., an audible tone is produced), when BUTTON3 is pressed,
// and not driven (i.e., silent), when BUTTON3 is released.
//
// To assist you, we have written some code below that will test R18:
// If R18 contains zero, then:
// any code between ex36_zero and "rjmp end_ex36" will execute.
// Else, if R18 is not zero, then:
// any code between ex36_nonzero and end_ex36 will execute.
// Write your code for Ex 3.6 anywhere below this line
cpi r18, 0
brne ex36_nonzero
ex36_zero:
rjmp end_ex36
ex36_nonzero:
end_ex36:
// Write your code for Ex 3.6 anywhere above this line
// END OF TUTORIAL03 EXERCISES //
// DO NOT EDIT BELOW THIS LINE //
end_loop_10ms:
// For sys_clk = 3.33 MHz, ~33k cycles in 10ms
//
// Let's implement a delay loop based on a 16-bit counter
//
// adiw takes 2 cycles to execute, we will also need at
// least one cycle for a test, so let's assume 4 cycles
// total, which we need to repeat ~8k times.
//
// 0x2000 = 8192, so we can just test bit 5 in high byte
delay_10ms:
adiw r30, 1 // 2 cycles
cpi r31, 0x20 // 1 cycle
brne delay_10ms // 1 cycle
// Reset high byte of delay loop counter
// (low byte should already be 0x00)
ldi r31, 0
// Every 10 of these cycles we need to execute the 100ms loop also
inc r29
cpi r29, 10
brne loop_10ms
// Reset 1s counter then jump to 1s loop
ldi r29, 0
rjmp loop_100ms
// We should never get here, but just in case
loop:
rjmp loop