I’m currently taking an online embedded programming course. This was our 4th programming assignment. The device is Microchip(Atmel) XMEGA-A3BU Xplained Development Kit, Mfr. Part Number: ATXMEGAA3BU-XPLD, the short name is Atxmega256A3BU. The device has an 8 bit data bus and a 16 bit address bus. I'm doing the development on Windows 10 in Microchip Studio 7 (a very poor clone of Visual Studio). I'm building the code without optimization. The optimizer has a habit of optimizing out my timing loops.
The assignment is to alternate between 2 LEDs and if one of the buttons is pushed change the behavior so that the LED associated with that button is pushed is lit. Current LED 0 is associated with button SW1 and LED 1 is associated with button SW2. We are to use the TCC0 timer to alternate between the 2 LEDs.
My question in addition to asking for a general review is the code for reading from and writing to a hardware address most often similar to the code in ReadReg()
and WriteReg()
in the code below? I'm asking about the pointer and not the volatile
keyword. I've known the volatile
keyword a long time.
Just FYI, the instructor really likes comments. If you are wondering about the change history, I am not using GIT for this class.
This assignment has been handed in.
reg_io_wrappers.h
/*
* reg_io_wrappers.h
*
* Functions to read and write the hardware registers on the device.
* Required for assignments from my class.
*
* Created: 4/27/2022 4:20:26 PM
* Author: pacmaninbw
*
* Change History:
* 5/11/2022 Changed added include for stdint-gcc.h to reg_io_wrappers.h,
* changed input and output types to uint8_t. Easier to find and change
* than unsigned char, better representation.
*/
#ifndef REG_IO_WRAPPERS_H_
#define REG_IO_WRAPPERS_H_
#include <stdint-gcc.h>
extern void WriteReg(uint16_t RegAddress, uint8_t Value);
extern uint8_t ReadReg(uint16_t RegAddress);
#endif /* REG_IO_WRAPPERS_H_ */
reg_io_wrappers.c
/*
* reg_io_wrappers.c
*
* Functions to read and write the hardware registers on the device.
* Required for assignments from my class.
*
* Created: 4/27/2022 4:08:13 PM
* Author: pacmaninbw
*
* Change History:
* 5/11/2022 Changed added include for stdint-gcc.h to reg_io_wrappers.h,
* changed input and output types to uint8_t. Easier to find and change
* than unsigned char, better representation.
*/
#include "reg_io_wrappers.h"
/* Write data to a hardware register */
void WriteReg(uint16_t RegAddress, uint8_t Value)
{
*((volatile unsigned char *)RegAddress) = Value;
}
/* Read data from a hardware register */
uint8_t ReadReg(uint16_t RegAddress)
{
// disable interrupts
uint8_t return_val = *((volatile uint8_t *)RegAddress);
// enable interrupts
return return_val;
}
main.c
/**
* Programming Assignment 4: Add timing using Clock to LED On/Off using switches
*
* 1. Create a code using Round Robin architecture to blink both LED’s when no
* switch is pressed like in previous assignment.
*
* 2. When any switch is pressed, then only blink the LED(s) associated to the
* switch number. Use the SW1 switch to control LED 0 and SW2 switch to
* control LED 1.
*
* 3. Create a function that controls the blink operation.
*
* 4. The main task loop should check the switch setting and make decisions
* whether to blink both LED's on at a time OR only blink the LEDS associated
* with the switches that are pressed.
*
* Change History
* 05/11/2022 - Moved call to delay function from main round robin to service_leds().
* This will allow buttons to interrupt the delay loop and force an early
* from the service_leds() function.
* Added service_buttons() function.
* Added include for stdint-gcc.h so that uint8_t is defined, better than
* putting unsigned char everywhere. Easier to modify if necessary.
*
* 05/14/2022 - 05/15/2022 - Converted the delay subroutine to use the
* TCC0 timer/counter from a timing loop.
*
* 05/16/2022 - Fixed bug in delay function, was not complementing the read back
* of the overflow flag. Moved the declaration of toggle into main(), there
* was no need for it to be global to the file.
*/
#include <stdint-gcc.h>
/* Include the hardware address macros. */
#include "devreg.h"
/*
* The I/O read and write wrapper functions are in a separate file, they will rarely
* need to be recompiled.
*/
#include "reg_io_wrappers.h"
/*
* Not including stdbool.h, using K & R solution instead.
*/
#define TRUE 1
#define FALSE 0
#if 0
/*
* Used for debugging purposes.
*/
static void lightRedLED(void)
{
uint8_t pin4 = 0x01 << 4;
WriteReg(PORTD_DIR_REG, pin4);
WriteReg(PORTD_OUTTGL_REG, ~pin4);
}
#endif
/*
* Non-interrupt service function.
* First determine if a button has been pushed, then determine which button
* it is. Set the global button pushed flag.
*
* The button read back is in bits 1 and 2 (pins 1 and 2). Since the toggle
* is an index into an array this needs to change to bits 0 and 1 so right
* shift 1 bit. Since the pins are low when the button is pushed we need to
* get the complement to find the proper value.
*/
static uint8_t service_buttons(uint8_t toggle)
{
/* Set PORTF direction to input
*/
WriteReg(BUTTON_ENABLE_REG, ENABLE_BUTTON_INPUT);
uint8_t current_pin_read = ReadReg(BUTTON_VALUE_REG); /* Read back if any buttons are pushed. */
current_pin_read = current_pin_read >> 1;
current_pin_read = ~current_pin_read & (uint8_t)0x03;
/*
* If no buttons are currently pushed return the current toggle value.
*/
current_pin_read = (current_pin_read)? current_pin_read : toggle;
return current_pin_read;
}
/*
* Keep each display state to approximately 1 to 2 seconds. Hopefully 1000
* loop executions equals 1 second. The delay function will be terminated
* if the button status has changed. Use the TCC0 timer for the delay.
*/
static void DelayUsingTCC0(uint8_t requestedDelay)
{
/*
* As per the instructions for this weeks lab,
* 1) Set CTRLA for prescaling divide by 1024
* 2) Since we want the counter to overflow based on only the 8 bits in
* the low counter register, set the high count register to all high.
* 3) Set the desired delay value in the lower 8 bits of the counter.
* 4) Make sure the overflow interrupt bit is cleared.
* 5) Poll the clock interrupt flags to check for overflow conditions.
*/
WriteReg(TCC0_INTFLAGS, CLEAR_OVFIF);
WriteReg(TCC0_CTRLA, CLK_CTRL_OPTS_DIV1024);
WriteReg(TCC0_COUNT_HI, 0xFF);
/*
* Subtract the desired delay from the overflow value for the lower
* 8 bits of the timer/counter. The overflow should occur when the
* lower 8 bits reaches 0xFF.
*/
WriteReg(TCC0_COUNT_LOW, 0xFF - requestedDelay);
/*
* When overflow occurs the overflow bit in the interrupt register goes low.
* Poll the interrupt flags for overflow.
*/
volatile uint8_t noOverflow = TRUE;
while(noOverflow)
{
volatile uint8_t overFlowCheck = ReadReg(TCC0_INTFLAGS);
noOverflow = ~overFlowCheck & OVFIF_MASK;
}
/* Make sure there are not interrupts for the rest of the program. */
WriteReg(TCC0_INTFLAGS, CLEAR_OVFIF);
}
/*
* Non-interrupt service function.
*
* Toggle the LEDs. First LED 0 then LED 1.
*/
#define PIN0 (uint8_t) 0x01
#define PIN1 (uint8_t) 0x02
#define PINS_0_AND_1 (uint8_t) 0x03
static void service_leds(uint8_t pin_index)
{
uint8_t pins[] = {PIN0, PIN1, PINS_0_AND_1};
uint8_t pin = pins[pin_index];
WriteReg(LED_ENABLE_REG, pin); /* Enable output on the specific pin(s) */
WriteReg(LED_TOGGLE_REG, ~pin); /* Drive the pin low. */
DelayUsingTCC0(250);
WriteReg(LED_ENABLE_REG, 0); /* Disable output on the pin */
}
int main (void)
{
uint8_t toggle = 0;
while (TRUE)
{
/*
* Simple Round Robin Architecture without interrupts.
* Buttons are a higher priority than the LEDs because the buttons provide
* user input and require a better response time. The buttons also change
* the status of which LEDs to display.
*/
toggle = service_buttons(toggle);
service_leds(toggle);
toggle = (toggle)? 0 : 1;
}
}
devreg.h
/*
* devreg.h
* Portable Register Addressing to allow the code using this file to port to
* other devices.
* Required for assignments from my class.
*
* Created: 4/27/2022 3:33:12 PM
* Author: pacmaninbw
*
* Change History
* Created 4/27/2022.Currently only contains macros to program the PORTR
* functionality, to enable and disable the LEDs. To make the LED
* programming more portable LED macros were added to hide the PORTR
* implementation on the device.
*
* 5/1/2022. Changed the PORT Address macros implementation, Ports can be added
* by copy and paste, select region, find and replace base port register
* name.
*
* 5/8/2022 Added PORTF Macros.
*
* 5/10/2022 Converted LED constants to use the complement of decimal numbers
* rather than Hex values.
*
* 5/14/2022 Added clock address offsets, CLOCK_TCC0 and the clock prescaler values
* for clock TCC0.
*
* 5/16/2022 Added Port D addresses, corrected copy paste errors in Ports B & C.
* Attempting to use red LED for debugging.
*/
#ifndef DEVREG_H_
#define DEVREG_H_
/*
* Clock Control Registers for TCC0
*/
#define CLOCK_TCC0 0x0800
#define CLOCK_CTRLA_OFFSET 0x00
#define CLOCK_CTRLB_OFFSET 0x01
#define CLOCK_CTRLC_OFFSET 0x02
#define CLOCK_CTRLD_OFFSET 0x03
#define CLOCK_CTRLE_OFFSET 0x04
#define CLOCK_INTERRUPT_CTRLA_OFFSET 0x06
#define CLOCK_INTERRUPT_CTRLB_OFFSET 0x07
#define CLOCK_CTRLF_CLEAR_OFFSET 0X08
#define CLOCK_CTRLF_SET_OFFSET 0X09
#define CLOCK_CTRLG_CLEAR_OFFSET 0X0A
#define CLOCK_CTRLG_SET_OFFSET 0X0B
#define CLOCK_INTERRUPT_FLAGS_OFFSET 0X0C
#define CLOCK_COUNTER_LOW_OFFSET 0X20
#define CLOCK_COUNTER_HI_OFFSET 0X21
/*
* Adding Clock Offsets
*/
#define ADD_CLOCK_CTRLA_OFFSET(baseAddress) \
(baseAddress + CLOCK_CTRLA_OFFSET)
#define ADD_CLOCK_CTRLB_OFFSET(baseAddress) \
(baseAddress + CLOCK_CTRLB_OFFSET)
#define ADD_CLOCK_CTRLC_OFFSET(baseAddress) \
(baseAddress + CLOCK_CTRLC_OFFSET)
#define ADD_CLOCK_CTRLD_OFFSET(baseAddress) \
(baseAddress + CLOCK_CTRLD_OFFSET)
#define ADD_CLOCK_CTRLE_OFFSET(baseAddress) \
(baseAddress + CLOCK_CTRLE_OFFSET)
#define ADD_CLOCK_INTERRUPT_CTRLA_OFFSET(baseAddress) \
(baseAddress + CLOCK_INTERRUPT_CTRLA_OFFSET)
#define ADD_CLOCK_INTERRUPT_CTRLB_OFFSET(baseAddress) \
(baseAddress + CLOCK_INTERRUPT_CTRLB_OFFSET)
#define ADD_CLOCK_CTRLF_CLEAR_OFFSET(baseAddress) \
(baseAddress + CLOCK_CTRLF_CLEAR_OFFSET)
#define ADD_CLOCK_CTRLF_SET_OFFSET(baseAddress) \
(baseAddress + CLOCK_CTRLF_SET_OFFSET)
#define ADD_CLOCK_CTRLG_CLEAR_OFFSET(baseAddress) \
(baseAddress + CLOCK_CTRLG_CLEAR_OFFSET)
#define ADD_CLOCK_CTRLG_SET_OFFSET(baseAddress) \
(baseAddress + CLOCK_CTRLG_SET_OFFSET)
#define ADD_CLOCK_INTERRUPT_FLAGS_OFFSET(baseAddress) \
(baseAddress + CLOCK_INTERRUPT_FLAGS_OFFSET)
#define ADDCLOCK_COUNTER_LOW_OFFSET(baseAddress) \
(baseAddress + CLOCK_COUNTER_LOW_OFFSET)
#define ADD_CLOCK_COUNTER_HI_OFFSET(baseAddress) \
(baseAddress + CLOCK_COUNTER_HI_OFFSET)
/*
* Clock Register Addresses
*/
/*
* TCC0 Clock Control Register Addresses
*/
#define TCC0_CTRLA ADD_CLOCK_CTRLA_OFFSET(CLOCK_TCC0)
#define TCC0_CTRLB ADD_CLOCK_CTRLB_OFFSET(CLOCK_TCC0)
#define TCC0_CTRLC ADD_CLOCK_CTRLC_OFFSET(CLOCK_TCC0)
#define TCC0_CTRLD ADD_CLOCK_CTRLD_OFFSET(CLOCK_TCC0)
#define TCC0_CTRLE ADD_CLOCK_CTRLE_OFFSET(CLOCK_TCC0)
#define TCC0_CTRLA_INT ADD_CLOCK_INTERRUPT_CTRLA_OFFSET(CLOCK_TCC0)
#define TCC0_CTRLB_INT ADD_CLOCK_INTERRUPT_CTRLB_OFFSET(CLOCK_TCC0)
#define TCCO_CTRLF_CLR ADD_CLOCK_CTRLF_CLEAR_OFFSET(CLOCK_TCC0)
#define TCC0_CTRLF_SET ADD_CLOCK_CTRLF_SET_OFFSET(CLOCK_TCC0)
#define TCCO_CTRLG_CLR ADD_CLOCK_CTRLG_CLEAR_OFFSET(CLOCK_TCC0)
#define TCC0_CTRLG_SET ADD_CLOCK_CTRLG_SET_OFFSET(CLOCK_TCC0)
#define TCC0_INTFLAGS ADD_CLOCK_INTERRUPT_FLAGS_OFFSET(CLOCK_TCC0)
#define TCC0_COUNT_LOW ADDCLOCK_COUNTER_LOW_OFFSET(CLOCK_TCC0)
#define TCC0_COUNT_HI ADD_CLOCK_COUNTER_HI_OFFSET(CLOCK_TCC0)
/*
* Clock Control Options and Prescaler Settings
*/
#define CLK_CTRL_OPTS_OFF (uint8_t) 0X00
#define CLK_CTRL_OPTS_DIV1 (uint8_t) 0X01
#define CLK_CTRL_OPTS_DIV2 (uint8_t) 0X02
#define CLK_CTRL_OPTS_DIV4 (uint8_t) 0X03
#define CLK_CTRL_OPTS_DIV8 (uint8_t) 0X04
#define CLK_CTRL_OPTS_DIV64 (uint8_t) 0X05
#define CLK_CTRL_OPTS_DIV256 (uint8_t) 0X06
#define CLK_CTRL_OPTS_DIV1024 (uint8_t) 0X07
/*
* Other Clock Control settings
*/
#define CLEAR_OVFIF (uint8_t) 0x01
#define OVFIF_MASK (uint8_t) 0x01
// LED control values
// For this device there are 2 LEDs, so there are 4 LED states, all LEDs off,
// all LEDs on, LED 0 on, LED 1 on.
// The yellow LEDs are controlled by pins 0 and 1 in PORTR. The LED controlled
// by pin 0 will be called LED 0 and the LED controlled by pin 1 will be called
// LED 1. When driving low on either pin 0 or pin 1 the associated LED will
// light up.
#define ALL_LEDS_OFF (uint8_t) ~0x00
#define ALL_LEDS_ON (uint8_t) ~0x03
#define LED_0_ON (uint8_t) ~0x01
#define LED_1_ON (uint8_t) ~0x02
#define LED_MAX_STATES 4
#define LED_STATE_MASK 0x03 /* The 2 LSBs in the PORT R register */
#define ENABLE_ALL_LEDS (uint8_t) 0x03
#define TURN_OFF_ALL_LEDS (uint8_t) 0x03
#define PORT_DIR_OUTPUT 0xFF /* Page 148 of the Manual Bits 0 and 1 output */
#define PORT_DIR_INPUT 0xFC /* Bits 0 and 1 input */
// Device Port Address Offsets
// These offsets are documented on page 160 of the manual
// Atmel-8331-8-and-16-bit-AVR-Microcontroller-XMEGA-AU_Manual.pdf
#define PORT_DIR_OFFSET 0x00
#define PORT_DIRSET_OFFSET 0x01
#define PORT_DIRCLR_OFFSET 0X02
#define PORT_DIRTGL_OFFSET 0X03
#define PORT_OUT_OFFSET 0x04
#define PORT_OUTSET_OFFSET 0x05
#define PORT_OUTCLR_OFFSET 0x06
#define PORT_OUTTGL_OFFSET 0x07
#define PORT_IN_OFFSET 0x08
// Adding Device Port Offsets
#define ADD_PORT_DIR_OFFSET(baseAddress) \
(baseAddress + PORT_DIR_OFFSET)
#define ADD_PORT_DIRSET_OFFSET(baseAddress) \
(baseAddress + PORT_DIRSET_OFFSET)
#define ADD_PORT_DIRCLR_OFFSET(baseAddress) \
(baseAddress + PORT_DIRCLR_OFFSET)
#define ADD_PORT_DIRTGL_OFFSET(baseAddress) \
(baseAddress + PORT_DIRTGL_OFFSET)
#define ADD_PORT_OUT_OFFSET(baseAddress) \
(baseAddress + PORT_OUT_OFFSET)
#define ADD_PORT_OUTSET_OFFSET(baseAddress) \
(baseAddress + PORT_OUTSET_OFFSET)
#define ADD_PORT_OUTCLR_OFFSET(baseAddress) \
(baseAddress + PORT_OUTCLR_OFFSET)
#define ADD_PORT_OUTTGL_OFFSET(baseAddress) \
(baseAddress + PORT_OUTTGL_OFFSET)
#define ADD_PORT_IN_OFFSET(baseAddress) \
(baseAddress + PORT_IN_OFFSET)
/* PORT R Device Addresses */
#define PORTR_BASE_ADDRESS 0x07E0
#define PORTR_DIR_REG ADD_PORT_DIR_OFFSET(PORTR_BASE_ADDRESS)
#define PORTR_DIRSET_REG ADD_PORT_DIRSET_OFFSET(PORTR_BASE_ADDRESS)
#define PORTR_DIRCLR_REG ADD_PORT_DIRCLR_OFFSET(PORTR_BASE_ADDRESS)
#define PORTR_DIRTGL_REG ADD_PORT_DIRTGL_OFFSET(PORTR_BASE_ADDRESS)
#define PORTR_OUT_REG ADD_PORT_OUT_OFFSET(PORTR_BASE_ADDRESS)
#define PORTR_OUTSET_REG ADD_PORT_OUTSET_OFFSET(PORTR_BASE_ADDRESS)
#define PORTR_OUTCLR_REG ADD_PORT_OUTCLR_OFFSET(PORTR_BASE_ADDRESS)
#define PORTR_OUTTGL_REG ADD_PORT_OUTTGL_OFFSET(PORTR_BASE_ADDRESS)
#define PORTR_IN_REG ADD_PORT_IN_OFFSET(PORTR_BASE_ADDRESS)
/* PORT F Device Addresses */
#define PORTF_BASE_ADDRESS 0x06A0
#define PORTF_DIR_REG ADD_PORT_DIR_OFFSET(PORTF_BASE_ADDRESS)
#define PORTF_DIRSET_REG ADD_PORT_DIRSET_OFFSET(PORTF_BASE_ADDRESS)
#define PORTF_DIRCLR_REG ADD_PORT_DIRCLR_OFFSET(PORTF_BASE_ADDRESS)
#define PORTF_DIRTGL_REG ADD_PORT_DIRTGL_OFFSET(PORTF_BASE_ADDRESS)
#define PORTF_OUT_REG ADD_PORT_OUT_OFFSET(PORTF_BASE_ADDRESS)
#define PORTF_OUTSET_REG ADD_PORT_OUTSET_OFFSET(PORTF_BASE_ADDRESS)
#define PORTF_OUTCLR_REG ADD_PORT_OUTCLR_OFFSET(PORTF_BASE_ADDRESS)
#define PORTF_OUTTGL_REG ADD_PORT_OUTTGL_OFFSET(PORTF_BASE_ADDRESS)
#define PORTF_IN_REG ADD_PORT_IN_OFFSET(PORTF_BASE_ADDRESS)
/* PORT A Device Addresses */
#define PORTA_BASE_ADDRESS 0x0600
#define PORTA_DIR_REG ADD_PORT_DIR_OFFSET(PORTA_BASE_ADDRESS)
#define PORTA_DIRSET_REG ADD_PORT_DIRSET_OFFSET(PORTA_BASE_ADDRESS)
#define PORTA_DIRCLR_REG ADD_PORT_DIRCLR_OFFSET(PORTA_BASE_ADDRESS)
#define PORTA_DIRTGL_REG ADD_PORT_DIRTGL_OFFSET(PORTA_BASE_ADDRESS)
#define PORTA_OUT_REG ADD_PORT_OUT_OFFSET(PORTA_BASE_ADDRESS)
#define PORTA_OUTSET_REG ADD_PORT_OUTSET_OFFSET(PORTA_BASE_ADDRESS)
#define PORTA_OUTCLR_REG ADD_PORT_OUTCLR_OFFSET(PORTA_BASE_ADDRESS)
#define PORTA_OUTTGL_REG ADD_PORT_OUTTGL_OFFSET(PORTA_BASE_ADDRESS)
#define PORTA_IN_REG ADD_PORT_IN_OFFSET(PORTA_BASE_ADDRESS)
/* PORT B Device Addresses */
#define PORTB_BASE_ADDRESS 0x0620
#define PORTB_DIR_REG ADD_PORT_DIR_OFFSET(PORTB_BASE_ADDRESS)
#define PORTB_DIRSET_REG ADD_PORT_DIRSET_OFFSET(PORTB_BASE_ADDRESS)
#define PORTB_DIRCLR_REG ADD_PORT_DIRCLR_OFFSET(PORTB_BASE_ADDRESS)
#define PORTB_DIRTGL_REG ADD_PORT_DIRTGL_OFFSET(PORTB_BASE_ADDRESS)
#define PORTB_OUT_REG ADD_PORT_OUT_OFFSET(PORTB_BASE_ADDRESS)
#define PORTB_OUTSET_REG ADD_PORT_OUTSET_OFFSET(PORTB_BASE_ADDRESS)
#define PORTB_OUTCLR_REG ADD_PORT_OUTCLR_OFFSET(PORTB_BASE_ADDRESS)
#define PORTB_OUTTGL_REG ADD_PORT_OUTTGL_OFFSET(PORTB_BASE_ADDRESS)
#define PORTB_IN_REG ADD_PORT_IN_OFFSET(PORTB_BASE_ADDRESS)
/* PORT C Device Addresses */
#define PORTC_BASE_ADDRESS 0x0640
#define PORTC_DIR_REG ADD_PORT_DIR_OFFSET(PORTC_BASE_ADDRESS)
#define PORTC_DIRSET_REG ADD_PORT_DIRSET_OFFSET(PORTC_BASE_ADDRESS)
#define PORTC_DIRCLR_REG ADD_PORT_DIRCLR_OFFSET(PORTC_BASE_ADDRESS)
#define PORTC_DIRTGL_REG ADD_PORT_DIRTGL_OFFSET(PORTC_BASE_ADDRESS)
#define PORTC_OUT_REG ADD_PORT_OUT_OFFSET(PORTC_BASE_ADDRESS)
#define PORTC_OUTSET_REG ADD_PORT_OUTSET_OFFSET(PORTC_BASE_ADDRESS)
#define PORTC_OUTCLR_REG ADD_PORT_OUTCLR_OFFSET(PORTC_BASE_ADDRESS)
#define PORTC_OUTTGL_REG ADD_PORT_OUTTGL_OFFSET(PORTC_BASE_ADDRESS)
#define PORTC_IN_REG ADD_PORT_IN_OFFSET(PORTC_BASE_ADDRESS)
/* PORT D Device Addresses */
#define PORTD_BASE_ADDRESS 0x0660
#define PORTD_DIR_REG ADD_PORT_DIR_OFFSET(PORTD_BASE_ADDRESS)
#define PORTD_DIRSET_REG ADD_PORT_DIRSET_OFFSET(PORTD_BASE_ADDRESS)
#define PORTD_DIRCLR_REG ADD_PORT_DIRCLR_OFFSET(PORTD_BASE_ADDRESS)
#define PORTD_DIRTGL_REG ADD_PORT_DIRTGL_OFFSET(PORTD_BASE_ADDRESS)
#define PORTD_OUT_REG ADD_PORT_OUT_OFFSET(PORTD_BASE_ADDRESS)
#define PORTD_OUTSET_REG ADD_PORT_OUTSET_OFFSET(PORTD_BASE_ADDRESS)
#define PORTD_OUTCLR_REG ADD_PORT_OUTCLR_OFFSET(PORTD_BASE_ADDRESS)
#define PORTD_OUTTGL_REG ADD_PORT_OUTTGL_OFFSET(PORTD_BASE_ADDRESS)
#define PORTD_IN_REG ADD_PORT_IN_OFFSET(PORTD_BASE_ADDRESS)
/*
* Portable names for device registers does not require knowledge of device
*/
#define LED_ENABLE_REG PORTR_DIR_REG
#define LED_TOGGLE_REG PORTR_OUTTGL_REG
#define ENABLE_LEDS PORT_DIR_OUTPUT
#define DISABLE_LEDS PORT_DIR_INPUT
#define LEDS_OFF_REG PORTR_OUT_REG
/*
* Buttons
* The SW1 and SW2 button input is available on PORTF PIN1 and PIN2 respectively
* as documented on page 10 of doc8394.pdf.
*/
#define SW1_AND_SW2_ARE_PRESSED (uint8_t) ~0x06 // Pins 1 and 2 are low
#define SW1_IS_PRESSED (uint8_t) ~0x02 // Pin 1 is low
#define SW2_IS_PRESSED (uint8_t) ~0x04 // Pin 2 is low
#define BUTTON_ENABLE_REG PORTF_DIR_REG
#define BUTTON_VALUE_REG PORTF_IN_REG
#define ENABLE_BUTTON_INPUT (uint8_t) ~0x06
#endif /* DEVREG_H_ */
[1]: https://i.stack.imgur.com/g0zPK.jpg