diff --git a/src/macros.h b/src/macros.h new file mode 100644 index 0000000000000000000000000000000000000000..939eae1e85624a861fc603a84781d1b0bb12e8a5 --- /dev/null +++ b/src/macros.h @@ -0,0 +1,48 @@ +/* + * macros.h + * + * Created: 2021-11-04 14:11:05 + * Author: benra10 + */ + + +#ifndef MACROS_H_ +#define MACROS_H_ + +// Macros for writing to I/O: +// There are many ways to write to PORT registers. +// Method 1. Simplest PORT method. Example for setting PA20 on PORTA. Note PORT_PA20 and not PIN_PA20 +// PORTA.OUTSET.reg = PORT_PA20 +// Method 2. Quicker method of PORT. Not sure if it is much faster than method 1 but it is more "compatible" with method nr 3. +// port_nr is in this case 0 for PORTA, 1 for PORTB and so on. +// PORT->Group[port_nr].OUTSET.reg = PORT_PA20 +// Method nr 3. Much quicker method that uses the direct access IOBUS. (If any optimization is enabled, otherwise difference is smaller). +// PORT_IOBUS->Group[port_nr].OUTSET.reg = PORT_PA20 +// Drawback is that for using IOBUS the constant sampling of used pins (in groups of 8) must be enabled. +// This consumes some power. +// Recommendation: Use method nr 2 and 3. Nr 2 if need to use minimum of power and 3 if need for maximal speed. +// Note: Data sheet says that only Data Output Value, Data Input Value and Pin Direction registers can be accessed through IOBUS operation. +// But practically test has shown that all PORT register can be accessed. For example PINCFG. +// Read more here about writing to ports: +// https://electronics.stackexchange.com/questions/139117/atmels-arm-programming-without-asf +// https://community.atmel.com/forum/getting-started-arm-3 +// https://www.avrfreaks.net/forum/considerations-using-iobus-port-access + +#define PORT_SET_PIN(port_nr,port_pin) PORT_IOBUS->Group[port_nr].OUTSET.reg = port_pin // Set to 1; Time with 40MHz is 190nsec +#define PORT_CLR_PIN(port_nr,port_pin) PORT_IOBUS->Group[port_nr].OUTCLR.reg = port_pin // Set to 0 +#define PORT_TOGGLE_PIN(port_nr,port_pin) PORT_IOBUS->Group[port_nr].OUTTGL.reg = port_pin // Toggle pin +#define PORT_OUTPUT_PIN(port_nr,port_pin) PORT_IOBUS->Group[port_nr].DIRSET.reg = port_pin // Set pin to output +#define PORT_INPUT_PIN(port_nr,port_pin) PORT_IOBUS->Group[port_nr].DIRCLR.reg = port_pin // port.DIRCLR.reg = pin // Set pin to input +#define PORT_INPUT_PIN_EN(port_nr,port_pin) PORT->Group[port_nr].PINCFG[port_pin].bit.INEN = 1 // Enable input buffer (needed to be able to read a pin) +#define PORT_READ_PIN(port_nr,port_pin) PORT_IOBUS->Group[port_nr].IN[port_pin] // Read a pin +#define PORT_READ(port_nr) PORT->Group[port_nr].IN.reg // Read a port +#define PORT_SET_CTRLSAMPLING(port_nr,port_pin) PORT->Group[port_nr].CTRL.reg |= port_pin; // Enable continuous sampling of a pin group (always in groups of 8) +#define PORT_CLR_CTRLSAMPLING(port_nr,port_pin) PORT->Group[port_nr].CTRL.reg &= ~port_pin; // Remove continuous sampling of a pin group +#define PORT_PULL_PIN_EN(port_nr,port_pin) PORT->Group[port_nr].PINCFG[port_pin].PULLEN=1 // Enable pull on a pin (Typ 40 kohm). Data value defines pull-up (1) or pull-down (0). Not on PA24 and PA25 +#define PORT_PULL_PIN_DIS(port_nr,port_pin) PORT->Group[port_nr].PINCFG[port_pin].PULLEN=0 // Disable pull on a pin +#define PORT_PULL_PIN_DRIVE_STRONG(port_nr,port_pin) PORT->Group[port_nr].PINCFG[port_pin].DRVSTR=1 // Enable strong drive strength on a pin. (~3mA, twice for VCC=3.6V). Not on PA24 and PA25 +#define PORT_PULL_PIN_DRIVE_WEAK(port_nr,port_pin) PORT->Group[port_nr].PINCFG[port_pin].DRVSTR=1 // Disable strong drive strength on a pin. (~1mA, twice for VCC=3.6V) + +// Tip: Example of other register or variable fiddling: SYSCTRL->VREG.bit.RUNSTDBY = 1 + +#endif /* MACROS_H_ */ \ No newline at end of file