DxCore
DxCore copied to clipboard
Improvements to pinConfigure
Due to limited time the last six months (I have two small kids now, life is busy...) I haven't been able to catch up to all the work you have been putting into DxCore and megaTinyCore.
Anyways, I decided to implement pinConfigure to MegaCoreX, because I see the benefits of having such functionality. It works well, but is so compact and optimized it's very difficult to keep track of what's going on without reading in the datasheets and the io.h file at the same time.
The first improvement would be to convert this into a template function. I've done it, and it works great. Instead of having to OR the pin settings together, you can just add them as separate parameters.
pinConfigure(PIN_PA0, PIN_DIR_OUT);
pinConfigure(PIN_PA1, PIN_DIR_OUT, PIN_OUT_HIGH, PIN_INVERT_SET);
pinConfigure(PIN_PA1, PIN_DIR_IN, PIN_PULLUP_SET);
The second improvement is to use a typedef enum instead of defined constants that provides no guard rails. By using enums, the user is only allowed to pass the PIN constants, unless not casted. We done need any ::'s The will still appear and work with
What do you think? Here's what all this looks like (Because this is for MegaCoreX, I've removed the MVIO part):
typedef enum
{
// OUTPUT
PIN_DIR_SET = 0x0001,
PIN_DIRSET = 0x0001,
PIN_DIR_OUTPUT = 0x0001,
PIN_DIR_OUT = 0x0001,
// INPUT
PIN_DIR_CLR = 0x0002,
PIN_DIRCLR = 0x0002,
PIN_DIR_INPUT = 0x0002,
PIN_DIR_IN = 0x0002,
// TOGGLE INPUT/OUTPUT
PIN_DIR_TGL = 0x0003,
PIN_DIRTGL = 0x0003,
PIN_DIR_TOGGLE = 0x0003,
// HIGH
PIN_OUT_SET = 0x0004,
PIN_OUTSET = 0x0004,
PIN_OUT_HIGH = 0x0004,
// LOW
PIN_OUT_CLR = 0x0008,
PIN_OUTCLR = 0x0008,
PIN_OUT_LOW = 0x0008,
// CHANGE/TOGGLE
PIN_OUT_TGL = 0x000C,
PIN_OUTTGL = 0x000C,
PIN_OUT_TOGGLE = 0x000C,
//Interrupt disabled but input buffer enabled
PIN_ISC_ENABLE = 0x0080,
PIN_INPUT_ENABLE = 0x0080,
// Interrupt on change
PIN_ISC_CHANGE = 0x0090,
PIN_INT_CHANGE = 0x0090,
// Interrupt on rising edge
PIN_ISC_RISE = 0x00A0,
PIN_INT_RISE = 0x00A0,
// Interrupt on falling edge
PIN_ISC_FALL = 0x00B0,
PIN_INT_FALL = 0x00B0,
// Interrupt and input buffer disabled
PIN_ISC_DISABLE = 0x00C0,
PIN_INPUT_DISABLE = 0x00C0,
// Interrupt enabled with sense on low level
PIN_ISC_LEVEL = 0x00D0,
PIN_INT_LEVEL = 0x00D0,
// PULLUP ON
PIN_PULLUP_ON = 0x0100,
PIN_PULLUP = 0x0100,
PIN_PULLUP_SET = 0x0100,
// PULLUP OFF
PIN_PULLUP_OFF = 0x0200,
PIN_PULLUP_CLR = 0x0200,
PIN_NOPULLUP = 0x0200,
// PULLUP TOGGLE
PIN_PULLUP_TGL = 0x0300,
PIN_PULLUP_TOGGLE = 0x0300,
// PIN INVERT ON
PIN_INVERT_ON = 0x4000,
PIN_INVERT_SET = 0x4000,
// PIN INVERT OFF
PIN_INVERT_OFF = 0x8000,
PIN_INVERT_CLR = 0x8000,
// PIN_INVERT_TOGGLE
PIN_INVERT_TGL = 0xC000,
PIN_INVERT_TOGGLE = 0xC000,
} pin_configure_t;
// Helper function to catch the last argument
pin_configure_t pinConfigure(const uint8_t digital_pin, const pin_configure_t mode)
{
(void)digital_pin;
return mode;
}
// PinConfigure variadic template function
template<typename MODE, typename... MODES>
void pinConfigure(const uint8_t digital_pin, const MODE& mode, const MODES&... modes)
{
// Start by or-ing together the arguments
uint8_t pin_config = pinConfigure(digital_pin, mode) | pinConfigure(digital_pin, modes...);
uint8_t bit_mask = digitalPinToBitMask(digital_pin);
if(bit_mask == NOT_A_PIN || !pin_config) // Return if digital pin is invalid or the other parameters or out to zero
return;
uint8_t bit_pos = digitalPinToBitPosition(digital_pin);
volatile uint8_t *portbase = (volatile uint8_t*) digitalPinToPortStruct(digital_pin);
// Write to selected pin direction register
uint8_t setting = pin_config & 0x03; // Mask out direction bits (DIR, DIRSET, DIRCLR, DIRTGL)
if(setting)
*(portbase + setting) = bit_mask;
// Write to selected output register
pin_config >>= 2;
setting = pin_config & 0x03;
if(setting)
*(portbase + 4 + setting) = bit_mask;
// Return if there is nothing more to configure
if(!(pin_config & 0x3FFC))
return;
uint8_t oldSREG = SREG; // Store SREG
cli(); // Disable interrupts
// PINnCTRL register
pin_config >>= 2;
uint8_t pinncfg = *(portbase + 0x10 + bit_pos);
// Input sense configuration (ISC)
if(pin_config & 0x08)
pinncfg = (pinncfg & 0xF8) | (pin_config & PORT_ISC_gm);
// Pullup resistor
uint8_t temp = pin_config & 0x30;
if(temp)
{
if(temp == 0x30)
pinncfg ^= PORT_PULLUPEN_bm; // Toggle pullup
else if(temp == 0x20)
pinncfg &= ~(PORT_PULLUPEN_bm); // Clear pullup
else
pinncfg |= PORT_PULLUPEN_bm; // Set pullup
}
// Invert pin
pin_config >>= 8;
temp = pin_config & 0x0C;
if(temp)
{
if(temp == 0x0C)
pinncfg ^= PORT_INVEN_bm; // Toggle invert
else if(temp == 0x08)
pinncfg &= ~(PORT_INVEN_bm); // Clear
else
pinncfg |= PORT_INVEN_bm; // Set
}
// Write to PINnCTRL register
*(portbase + 0x10 + bit_pos) = pinncfg;
// Restore SREG
SREG = oldSREG;
}
Damn, that looks awesome - I was never happy with the need to OR the constants together, but templates are a dark art which I do not have experience with.
Hmm, okay - so I do NOT know how to make that compile... Which isnt surprising since I don't really know how to use templates much less variadic ones.
Though uint8_t pin_config
should definitely be uint16_t
The issue may be because your cores already have pinConfigure defined. Try removing or renaming them. Here is an updated version where pin_configure_t is a 16-bit enum.
// Compiles with MegaCoreX
typedef enum : uint16_t
{
// OUTPUT
PIN_DIR_SET = 0x0001,
PIN_DIRSET = 0x0001,
PIN_DIR_OUTPUT = 0x0001,
PIN_DIR_OUT = 0x0001,
// INPUT
PIN_DIR_CLR = 0x0002,
PIN_DIRCLR = 0x0002,
PIN_DIR_INPUT = 0x0002,
PIN_DIR_IN = 0x0002,
// TOGGLE INPUT/OUTPUT
PIN_DIR_TGL = 0x0003,
PIN_DIRTGL = 0x0003,
PIN_DIR_TOGGLE = 0x0003,
// HIGH
PIN_OUT_SET = 0x0004,
PIN_OUTSET = 0x0004,
PIN_OUT_HIGH = 0x0004,
// LOW
PIN_OUT_CLR = 0x0008,
PIN_OUTCLR = 0x0008,
PIN_OUT_LOW = 0x0008,
// CHANGE/TOGGLE
PIN_OUT_TGL = 0x000C,
PIN_OUTTGL = 0x000C,
PIN_OUT_TOGGLE = 0x000C,
//Interrupt disabled but input buffer enabled
PIN_ISC_ENABLE = 0x0080,
PIN_INPUT_ENABLE = 0x0080,
// Interrupt on change
PIN_ISC_CHANGE = 0x0090,
PIN_INT_CHANGE = 0x0090,
// Interrupt on rising edge
PIN_ISC_RISE = 0x00A0,
PIN_INT_RISE = 0x00A0,
// Interrupt on falling edge
PIN_ISC_FALL = 0x00B0,
PIN_INT_FALL = 0x00B0,
// Interrupt and input buffer disabled
PIN_ISC_DISABLE = 0x00C0,
PIN_INPUT_DISABLE = 0x00C0,
// Interrupt enabled with sense on low level
PIN_ISC_LEVEL = 0x00D0,
PIN_INT_LEVEL = 0x00D0,
// PULLUP ON
PIN_PULLUP_ON = 0x0100,
PIN_PULLUP = 0x0100,
PIN_PULLUP_SET = 0x0100,
// PULLUP OFF
PIN_PULLUP_OFF = 0x0200,
PIN_PULLUP_CLR = 0x0200,
PIN_NOPULLUP = 0x0200,
// PULLUP TOGGLE
PIN_PULLUP_TGL = 0x0300,
PIN_PULLUP_TOGGLE = 0x0300,
// PIN INVERT ON
PIN_INVERT_ON = 0x4000,
PIN_INVERT_SET = 0x4000,
// PIN INVERT OFF
PIN_INVERT_OFF = 0x8000,
PIN_INVERT_CLR = 0x8000,
// PIN_INVERT_TOGGLE
PIN_INVERT_TGL = 0xC000,
PIN_INVERT_TOGGLE = 0xC000,
} pin_configure_t;
pin_configure_t pinConfigure(const uint8_t digital_pin, const pin_configure_t mode)
{
(void)digital_pin;
return mode;
}
template <typename MODE, typename... MODES>
void pinConfigure(const uint8_t digital_pin, const MODE& mode, const MODES&... modes)
{
// Start by or-ing together the arguments
uint8_t pin_config = pinConfigure(digital_pin, mode) | pinConfigure(digital_pin, modes...);
uint8_t bit_mask = digitalPinToBitMask(digital_pin);
if(bit_mask == NOT_A_PIN || !pin_config) // Return if digital pin is invalid or the other parameters or out to zero
return;
uint8_t bit_pos = digitalPinToBitPosition(digital_pin);
volatile uint8_t *portbase = (volatile uint8_t*) digitalPinToPortStruct(digital_pin);
// Write to selected pin direction register
uint8_t setting = pin_config & 0x03; // Mask out direction bits (DIR, DIRSET, DIRCLR, DIRTGL)
if(setting)
*(portbase + setting) = bit_mask;
// Write to selected output register
pin_config >>= 2;
setting = pin_config & 0x03;
if(setting)
*(portbase + 4 + setting) = bit_mask;
// Return if there is nothing more to configure
if(!(pin_config & 0x3FFC))
return;
uint8_t oldSREG = SREG; // Store SREG
cli(); // Disable interrupts
// PINnCTRL register
pin_config >>= 2;
uint8_t pinncfg = *(portbase + 0x10 + bit_pos);
// Input sense configuration (ISC)
if(pin_config & 0x08)
pinncfg = (pinncfg & 0xF8) | (pin_config & PORT_ISC_gm);
// Pullup resistor
uint8_t temp = pin_config & 0x30;
if(temp)
{
if(temp == 0x30)
pinncfg ^= PORT_PULLUPEN_bm; // Toggle pullup
else if(temp == 0x20)
pinncfg &= ~(PORT_PULLUPEN_bm); // Clear pullup
else
pinncfg |= PORT_PULLUPEN_bm; // Set pullup
}
// Invert pin
pin_config >>= 8;
temp = pin_config & 0x0C;
if(temp)
{
if(temp == 0x0C)
pinncfg ^= PORT_INVEN_bm; // Toggle invert
else if(temp == 0x08)
pinncfg &= ~(PORT_INVEN_bm); // Clear
else
pinncfg |= PORT_INVEN_bm; // Set
}
// Write to PINnCTRL register
*(portbase + 0x10 + bit_pos) = pinncfg;
// Restore SREG
SREG = oldSREG;
}
void setup() {
}
void loop() {
pinConfigure(13, PIN_OUT_SET, PIN_DIRCLR);
delay(1000);
}
Ah, you need inline
in order to get it to compile:
https://github.com/MCUdude/MegaCoreX/commit/47ef471683d9856af8147705d410bf096ba282c8
Hmm, uhhh...
uint8_t pin_config = pinConfigure(digital_pin, mode) | pinConfigure(digital_pin, modes...);
pinConfigure with more than two modes fails to compile, complaining of there being no operator | defined for pin_configure_t and void - because pinConfigure with a single mode argument calls the helper function which returns a pin_configure_t, while the one with more argument options returns void. This looks like a tricky thing to fix if I'm not missing something.
This looks like a tricky thing to fix if I'm not missing something.
Happy new year!
Nah, just me being dumb. Fixed now. https://github.com/MCUdude/MegaCoreX/commit/a7dd83c062ea4f0284bf243bbe4c4025e7dcd979
Happy new year to you!
Huh, okay, yeah, now it;s compiling and looks to be working. I notice that the flash usage of a single call to it is competitive with a call to the old version, but as you call it more, it's flash usage grows markedly faster... Do you happen to know why this would be?
Huh, okay, yeah, now it;s compiling and looks to be working. I notice that the flash usage of a single call to it is competitive with a call to the old version, but as you call it more, it's flash usage grows markedly faster... Do you happen to know why this would be?
I'm not sure why it's that much larger. The thing about templates is that things are figured out at compile time, so in theory all the ORing and function calling should have been done by the compiler.
Have a look at the OR template function below. Give it a try if you have time. No matter what you put into it, as long as it's know at compile time, the size will not grow much at all.
template<typename T>
T orer(T first) {
return first;
}
template<typename T, typename... Args>
T orer(T first, Args... args) {
return first | orer(args...);
}
// call orer(arg1, arg2, arg3 etc)
Based on
void setup() {
pinConfigure(PIN_PA7, PIN_PULLUP_ON | PIN_ISC_DISABLE | PIN_INVERT_ON);
pinConfigure(PIN_PA7, PIN_DIR_SET | PIN_INPUT_ENABLE | PIN_INVERT_ON);
pinConfigure(PIN_PA7, PIN_OUT_CLR | PIN_DIR_SET| PIN_INPUT_DISABLE);
pinConfigure(PIN_PA6, PIN_PULLUP_ON | PIN_ISC_DISABLE| PIN_INVERT_ON);
pinConfigure(PIN_PA6, PIN_DIR_SET | PIN_INPUT_ENABLE| PIN_INVERT_ON);
pinConfigure(PIN_PA6, PIN_OUT_CLR | PIN_DIR_SET| PIN_INPUT_DISABLE);
pinConfigure(PIN_PA5, PIN_PULLUP_ON | PIN_ISC_DISABLE| PIN_INVERT_ON);
pinConfigure(PIN_PA5, PIN_DIR_SET | PIN_INPUT_ENABLE| PIN_INVERT_ON);
pinConfigure(PIN_PA5, PIN_OUT_CLR | PIN_DIR_SET| PIN_INPUT_DISABLE);
pinConfigure(PIN_PA4, PIN_PULLUP_ON | PIN_ISC_DISABLE| PIN_INVERT_ON);
pinConfigure(PIN_PA4, PIN_DIR_SET | PIN_INPUT_ENABLE| PIN_INVERT_ON);
pinConfigure(PIN_PA4, PIN_OUT_CLR | PIN_DIR_SET| PIN_INPUT_DISABLE);
}
void loop() {
}
vs
void setup() {
pinConfigure(PIN_PA7, PIN_PULLUP_ON | PIN_ISC_DISABLE | PIN_INVERT_ON);
pinConfigure(PIN_PA4, PIN_OUT_CLR | PIN_DIR_SET| PIN_INPUT_DISABLE);
}
void loop() {
}
744 vs 496 24.8 bytes per call.
With the equivalent (substitute |'s for commas): 1424 vs 1070 35.4 bytes per call.
Now compare:
void setup() {
pinConfigure(PIN_PA7, PIN_PULLUP_ON , PIN_ISC_DISABLE, PIN_INVERT_ON);
pinConfigure(PIN_PA6, PIN_DIR_SET , PIN_INPUT_ENABLE, PIN_INVERT_ON);
pinConfigure(PIN_PA5, PIN_OUT_CLR , PIN_DIR_SET, PIN_INPUT_DISABLE);
pinConfigure(PIN_PA4, PIN_PULLUP_ON , PIN_ISC_DISABLE, PIN_INVERT_ON);
pinConfigure(PIN_PA3, PIN_DIR_SET , PIN_INPUT_ENABLE, PIN_INVERT_ON);
pinConfigure(PIN_PA2, PIN_OUT_CLR , PIN_DIR_SET, PIN_INPUT_DISABLE);
pinConfigure(PIN_PA1, PIN_PULLUP_ON , PIN_ISC_DISABLE, PIN_INVERT_ON);
pinConfigure(PIN_PB0, PIN_DIR_SET , PIN_INPUT_ENABLE, PIN_INVERT_ON);
}
void loop() {
}
with
void setup() {
pinConfigure(PIN_PA7, PIN_PULLUP_ON , PIN_ISC_DISABLE, PIN_INVERT_ON);
pinConfigure(PIN_PA7, PIN_DIR_SET , PIN_INPUT_ENABLE, PIN_INVERT_ON);
pinConfigure(PIN_PA7, PIN_OUT_CLR , PIN_DIR_SET, PIN_INPUT_DISABLE);
pinConfigure(PIN_PA7, PIN_PULLUP_ON , PIN_ISC_DISABLE, PIN_INVERT_ON);
pinConfigure(PIN_PA7, PIN_DIR_SET , PIN_INPUT_ENABLE, PIN_INVERT_ON);
pinConfigure(PIN_PA7, PIN_OUT_CLR , PIN_DIR_SET, PIN_INPUT_DISABLE);
pinConfigure(PIN_PA7, PIN_PULLUP_ON , PIN_ISC_DISABLE, PIN_INVERT_ON);
pinConfigure(PIN_PA7, PIN_DIR_SET , PIN_INPUT_ENABLE, PIN_INVERT_ON);
}
void loop() {
}
1220 vs 1076 That's a 20 byte overhead for a different pin, whereas the overhead is only 6 bytes with the classic implementation.
What's even more horrifying is the comparison of the generated assembly in the calling section (shown for the first example with the 12 calls):
pinConfigure(PIN_PA7, PIN_PULLUP_ON | PIN_ISC_DISABLE | PIN_INVERT_ON);
24c: 60 ec ldi r22, 0xC0 ; 192
24e: 71 e4 ldi r23, 0x41 ; 65
250: 83 e0 ldi r24, 0x03 ; 3
252: 31 df rcall .-414 ; 0xb6 <pinConfigure>
pinConfigure(PIN_PA7, PIN_DIR_SET | PIN_INPUT_ENABLE | PIN_INVERT_ON);
254: 61 e8 ldi r22, 0x81 ; 129
256: 70 e4 ldi r23, 0x40 ; 64
258: 83 e0 ldi r24, 0x03 ; 3
25a: 2d df rcall .-422 ; 0xb6 <pinConfigure>
pinConfigure(PIN_PA7, PIN_OUT_CLR | PIN_DIR_SET| PIN_INPUT_DISABLE);
25c: 69 ec ldi r22, 0xC9 ; 201
25e: 70 e0 ldi r23, 0x00 ; 0
260: 83 e0 ldi r24, 0x03 ; 3
262: 29 df rcall .-430 ; 0xb6 <pinConfigure>
pinConfigure(PIN_PA6, PIN_PULLUP_ON | PIN_ISC_DISABLE| PIN_INVERT_ON);
264: 60 ec ldi r22, 0xC0 ; 192
266: 71 e4 ldi r23, 0x41 ; 65
268: 82 e0 ldi r24, 0x02 ; 2
26a: 25 df rcall .-438 ; 0xb6 <pinConfigure>
pinConfigure(PIN_PA6, PIN_DIR_SET | PIN_INPUT_ENABLE| PIN_INVERT_ON);
26c: 61 e8 ldi r22, 0x81 ; 129
26e: 70 e4 ldi r23, 0x40 ; 64
270: 82 e0 ldi r24, 0x02 ; 2
272: 21 df rcall .-446 ; 0xb6 <pinConfigure>
pinConfigure(PIN_PA6, PIN_OUT_CLR | PIN_DIR_SET| PIN_INPUT_DISABLE);
274: 69 ec ldi r22, 0xC9 ; 201
276: 70 e0 ldi r23, 0x00 ; 0
278: 82 e0 ldi r24, 0x02 ; 2
27a: 1d df rcall .-454 ; 0xb6 <pinConfigure>
pinConfigure(PIN_PA5, PIN_PULLUP_ON | PIN_ISC_DISABLE| PIN_INVERT_ON);
27c: 60 ec ldi r22, 0xC0 ; 192
27e: 71 e4 ldi r23, 0x41 ; 65
280: 81 e0 ldi r24, 0x01 ; 1
282: 19 df rcall .-462 ; 0xb6 <pinConfigure>
pinConfigure(PIN_PA5, PIN_DIR_SET | PIN_INPUT_ENABLE| PIN_INVERT_ON);
284: 61 e8 ldi r22, 0x81 ; 129
286: 70 e4 ldi r23, 0x40 ; 64
288: 81 e0 ldi r24, 0x01 ; 1
28a: 15 df rcall .-470 ; 0xb6 <pinConfigure>
pinConfigure(PIN_PA5, PIN_OUT_CLR | PIN_DIR_SET| PIN_INPUT_DISABLE);
28c: 69 ec ldi r22, 0xC9 ; 201
28e: 70 e0 ldi r23, 0x00 ; 0
290: 81 e0 ldi r24, 0x01 ; 1
292: 11 df rcall .-478 ; 0xb6 <pinConfigure>
pinConfigure(PIN_PA4, PIN_PULLUP_ON | PIN_ISC_DISABLE| PIN_INVERT_ON);
294: 60 ec ldi r22, 0xC0 ; 192
296: 71 e4 ldi r23, 0x41 ; 65
298: 80 e0 ldi r24, 0x00 ; 0
29a: 0d df rcall .-486 ; 0xb6 <pinConfigure>
pinConfigure(PIN_PA4, PIN_DIR_SET | PIN_INPUT_ENABLE| PIN_INVERT_ON);
29c: 61 e8 ldi r22, 0x81 ; 129
29e: 70 e4 ldi r23, 0x40 ; 64
2a0: 80 e0 ldi r24, 0x00 ; 0
2a2: 09 df rcall .-494 ; 0xb6 <pinConfigure>
pinConfigure(PIN_PA4, PIN_OUT_CLR | PIN_DIR_SET| PIN_INPUT_DISABLE);
2a4: 69 ec ldi r22, 0xC9 ; 201
2a6: 70 e0 ldi r23, 0x00 ; 0
2a8: 80 e0 ldi r24, 0x00 ; 0
2aa: 05 df rcall .-502 ; 0xb6 <pinConfigure>
Vs this - somehow it is doing a horrifyingly bad job of optimizing that.
pinConfigure(PIN_PA7, PIN_PULLUP_ON , PIN_ISC_DISABLE, PIN_INVERT_ON);
38e: c1 2c mov r12, r1
390: 80 e4 ldi r24, 0x40 ; 64
392: d8 2e mov r13, r24
394: c9 82 std Y+1, r12 ; 0x01
396: da 82 std Y+2, r13 ; 0x02
398: 90 ec ldi r25, 0xC0 ; 192
39a: e9 2e mov r14, r25
39c: f1 2c mov r15, r1
39e: eb 82 std Y+3, r14 ; 0x03
3a0: fc 82 std Y+4, r15 ; 0x04
3a2: 81 2c mov r8, r1
3a4: 99 24 eor r9, r9
3a6: 93 94 inc r9
3a8: 8d 82 std Y+5, r8 ; 0x05
3aa: 9e 82 std Y+6, r9 ; 0x06
3ac: 9e 01 movw r18, r28
3ae: 2f 5f subi r18, 0xFF ; 255
3b0: 3f 4f sbci r19, 0xFF ; 255
3b2: ae 01 movw r20, r28
3b4: 4d 5f subi r20, 0xFD ; 253
3b6: 5f 4f sbci r21, 0xFF ; 255
3b8: be 01 movw r22, r28
3ba: 6b 5f subi r22, 0xFB ; 251
3bc: 7f 4f sbci r23, 0xFF ; 255
3be: 83 e0 ldi r24, 0x03 ; 3
3c0: 7a de rcall .-780 ; 0xb6 <unsigned int pinConfigure<pin_configure_t, pin_configure_t, pin_configure_t>(unsigned char, pin_configure_t const&, pin_configure_t const&, pin_configure_t const&)>
pinConfigure(PIN_PA7, PIN_DIR_SET , PIN_INPUT_ENABLE, PIN_INVERT_ON);
3c2: c9 82 std Y+1, r12 ; 0x01
3c4: da 82 std Y+2, r13 ; 0x02
3c6: 30 e8 ldi r19, 0x80 ; 128
3c8: a3 2e mov r10, r19
3ca: b1 2c mov r11, r1
3cc: ab 82 std Y+3, r10 ; 0x03
3ce: bc 82 std Y+4, r11 ; 0x04
3d0: 01 e0 ldi r16, 0x01 ; 1
3d2: 10 e0 ldi r17, 0x00 ; 0
3d4: 0d 83 std Y+5, r16 ; 0x05
3d6: 1e 83 std Y+6, r17 ; 0x06
3d8: 9e 01 movw r18, r28
3da: 2f 5f subi r18, 0xFF ; 255
3dc: 3f 4f sbci r19, 0xFF ; 255
3de: ae 01 movw r20, r28
3e0: 4d 5f subi r20, 0xFD ; 253
3e2: 5f 4f sbci r21, 0xFF ; 255
3e4: be 01 movw r22, r28
3e6: 6b 5f subi r22, 0xFB ; 251
3e8: 7f 4f sbci r23, 0xFF ; 255
3ea: 83 e0 ldi r24, 0x03 ; 3
3ec: 64 de rcall .-824 ; 0xb6 <unsigned int pinConfigure<pin_configure_t, pin_configure_t, pin_configure_t>(unsigned char, pin_configure_t const&, pin_configure_t const&, pin_configure_t const&)>
pinConfigure(PIN_PA7, PIN_OUT_CLR , PIN_DIR_SET, PIN_INPUT_DISABLE);
3ee: e9 82 std Y+1, r14 ; 0x01
3f0: fa 82 std Y+2, r15 ; 0x02
3f2: 0b 83 std Y+3, r16 ; 0x03
3f4: 1c 83 std Y+4, r17 ; 0x04
3f6: 48 e0 ldi r20, 0x08 ; 8
3f8: 64 2e mov r6, r20
3fa: 71 2c mov r7, r1
3fc: 6d 82 std Y+5, r6 ; 0x05
3fe: 7e 82 std Y+6, r7 ; 0x06
400: 9e 01 movw r18, r28
402: 2f 5f subi r18, 0xFF ; 255
404: 3f 4f sbci r19, 0xFF ; 255
406: ae 01 movw r20, r28
408: 4d 5f subi r20, 0xFD ; 253
40a: 5f 4f sbci r21, 0xFF ; 255
40c: be 01 movw r22, r28
40e: 6b 5f subi r22, 0xFB ; 251
410: 7f 4f sbci r23, 0xFF ; 255
412: 83 e0 ldi r24, 0x03 ; 3
414: 50 de rcall .-864 ; 0xb6 <unsigned int pinConfigure<pin_configure_t, pin_configure_t, pin_configure_t>(unsigned char, pin_configure_t const&, pin_configure_t const&, pin_configure_t const&)>
pinConfigure(PIN_PA6, PIN_PULLUP_ON , PIN_ISC_DISABLE, PIN_INVERT_ON);
416: c9 82 std Y+1, r12 ; 0x01
418: da 82 std Y+2, r13 ; 0x02
41a: eb 82 std Y+3, r14 ; 0x03
41c: fc 82 std Y+4, r15 ; 0x04
41e: 8d 82 std Y+5, r8 ; 0x05
420: 9e 82 std Y+6, r9 ; 0x06
422: 9e 01 movw r18, r28
424: 2f 5f subi r18, 0xFF ; 255
426: 3f 4f sbci r19, 0xFF ; 255
428: ae 01 movw r20, r28
42a: 4d 5f subi r20, 0xFD ; 253
42c: 5f 4f sbci r21, 0xFF ; 255
42e: be 01 movw r22, r28
430: 6b 5f subi r22, 0xFB ; 251
432: 7f 4f sbci r23, 0xFF ; 255
434: 82 e0 ldi r24, 0x02 ; 2
436: 3f de rcall .-898 ; 0xb6 <unsigned int pinConfigure<pin_configure_t, pin_configure_t, pin_configure_t>(unsigned char, pin_configure_t const&, pin_configure_t const&, pin_configure_t const&)>
pinConfigure(PIN_PA6, PIN_DIR_SET , PIN_INPUT_ENABLE, PIN_INVERT_ON);
438: c9 82 std Y+1, r12 ; 0x01
43a: da 82 std Y+2, r13 ; 0x02
43c: ab 82 std Y+3, r10 ; 0x03
43e: bc 82 std Y+4, r11 ; 0x04
440: 0d 83 std Y+5, r16 ; 0x05
442: 1e 83 std Y+6, r17 ; 0x06
444: 9e 01 movw r18, r28
446: 2f 5f subi r18, 0xFF ; 255
448: 3f 4f sbci r19, 0xFF ; 255
44a: ae 01 movw r20, r28
44c: 4d 5f subi r20, 0xFD ; 253
44e: 5f 4f sbci r21, 0xFF ; 255
450: be 01 movw r22, r28
452: 6b 5f subi r22, 0xFB ; 251
454: 7f 4f sbci r23, 0xFF ; 255
456: 82 e0 ldi r24, 0x02 ; 2
458: 2e de rcall .-932 ; 0xb6 <unsigned int pinConfigure<pin_configure_t, pin_configure_t, pin_configure_t>(unsigned char, pin_configure_t const&, pin_configure_t const&, pin_configure_t const&)>
pinConfigure(PIN_PA6, PIN_OUT_CLR , PIN_DIR_SET, PIN_INPUT_DISABLE);
45a: e9 82 std Y+1, r14 ; 0x01
45c: fa 82 std Y+2, r15 ; 0x02
45e: 0b 83 std Y+3, r16 ; 0x03
460: 1c 83 std Y+4, r17 ; 0x04
462: 6d 82 std Y+5, r6 ; 0x05
464: 7e 82 std Y+6, r7 ; 0x06
466: 9e 01 movw r18, r28
468: 2f 5f subi r18, 0xFF ; 255
46a: 3f 4f sbci r19, 0xFF ; 255
46c: ae 01 movw r20, r28
46e: 4d 5f subi r20, 0xFD ; 253
470: 5f 4f sbci r21, 0xFF ; 255
472: be 01 movw r22, r28
474: 6b 5f subi r22, 0xFB ; 251
476: 7f 4f sbci r23, 0xFF ; 255
478: 82 e0 ldi r24, 0x02 ; 2
47a: 1d de rcall .-966 ; 0xb6 <unsigned int pinConfigure<pin_configure_t, pin_configure_t, pin_configure_t>(unsigned char, pin_configure_t const&, pin_configure_t const&, pin_configure_t const&)>
pinConfigure(PIN_PA5, PIN_PULLUP_ON , PIN_ISC_DISABLE, PIN_INVERT_ON);
47c: c9 82 std Y+1, r12 ; 0x01
47e: da 82 std Y+2, r13 ; 0x02
480: eb 82 std Y+3, r14 ; 0x03
482: fc 82 std Y+4, r15 ; 0x04
484: 8d 82 std Y+5, r8 ; 0x05
486: 9e 82 std Y+6, r9 ; 0x06
488: 9e 01 movw r18, r28
48a: 2f 5f subi r18, 0xFF ; 255
48c: 3f 4f sbci r19, 0xFF ; 255
48e: ae 01 movw r20, r28
490: 4d 5f subi r20, 0xFD ; 253
492: 5f 4f sbci r21, 0xFF ; 255
494: be 01 movw r22, r28
496: 6b 5f subi r22, 0xFB ; 251
498: 7f 4f sbci r23, 0xFF ; 255
49a: 81 e0 ldi r24, 0x01 ; 1
49c: 0c de rcall .-1000 ; 0xb6 <unsigned int pinConfigure<pin_configure_t, pin_configure_t, pin_configure_t>(unsigned char, pin_configure_t const&, pin_configure_t const&, pin_configure_t const&)>
pinConfigure(PIN_PA5, PIN_DIR_SET , PIN_INPUT_ENABLE, PIN_INVERT_ON);
49e: c9 82 std Y+1, r12 ; 0x01
4a0: da 82 std Y+2, r13 ; 0x02
4a2: ab 82 std Y+3, r10 ; 0x03
4a4: bc 82 std Y+4, r11 ; 0x04
4a6: 0d 83 std Y+5, r16 ; 0x05
4a8: 1e 83 std Y+6, r17 ; 0x06
4aa: 9e 01 movw r18, r28
4ac: 2f 5f subi r18, 0xFF ; 255
4ae: 3f 4f sbci r19, 0xFF ; 255
4b0: ae 01 movw r20, r28
4b2: 4d 5f subi r20, 0xFD ; 253
4b4: 5f 4f sbci r21, 0xFF ; 255
4b6: be 01 movw r22, r28
4b8: 6b 5f subi r22, 0xFB ; 251
4ba: 7f 4f sbci r23, 0xFF ; 255
4bc: 81 e0 ldi r24, 0x01 ; 1
4be: fb dd rcall .-1034 ; 0xb6 <unsigned int pinConfigure<pin_configure_t, pin_configure_t, pin_configure_t>(unsigned char, pin_configure_t const&, pin_configure_t const&, pin_configure_t const&)>
pinConfigure(PIN_PA5, PIN_OUT_CLR , PIN_DIR_SET, PIN_INPUT_DISABLE);
4c0: e9 82 std Y+1, r14 ; 0x01
4c2: fa 82 std Y+2, r15 ; 0x02
4c4: 0b 83 std Y+3, r16 ; 0x03
4c6: 1c 83 std Y+4, r17 ; 0x04
4c8: 6d 82 std Y+5, r6 ; 0x05
4ca: 7e 82 std Y+6, r7 ; 0x06
4cc: 9e 01 movw r18, r28
4ce: 2f 5f subi r18, 0xFF ; 255
4d0: 3f 4f sbci r19, 0xFF ; 255
4d2: ae 01 movw r20, r28
4d4: 4d 5f subi r20, 0xFD ; 253
4d6: 5f 4f sbci r21, 0xFF ; 255
4d8: be 01 movw r22, r28
4da: 6b 5f subi r22, 0xFB ; 251
4dc: 7f 4f sbci r23, 0xFF ; 255
4de: 81 e0 ldi r24, 0x01 ; 1
4e0: ea dd rcall .-1068 ; 0xb6 <unsigned int pinConfigure<pin_configure_t, pin_configure_t, pin_configure_t>(unsigned char, pin_configure_t const&, pin_configure_t const&, pin_configure_t const&)>
pinConfigure(PIN_PA4, PIN_PULLUP_ON , PIN_ISC_DISABLE, PIN_INVERT_ON);
4e2: c9 82 std Y+1, r12 ; 0x01
4e4: da 82 std Y+2, r13 ; 0x02
4e6: eb 82 std Y+3, r14 ; 0x03
4e8: fc 82 std Y+4, r15 ; 0x04
4ea: 8d 82 std Y+5, r8 ; 0x05
4ec: 9e 82 std Y+6, r9 ; 0x06
4ee: 9e 01 movw r18, r28
4f0: 2f 5f subi r18, 0xFF ; 255
4f2: 3f 4f sbci r19, 0xFF ; 255
4f4: ae 01 movw r20, r28
4f6: 4d 5f subi r20, 0xFD ; 253
4f8: 5f 4f sbci r21, 0xFF ; 255
4fa: be 01 movw r22, r28
4fc: 6b 5f subi r22, 0xFB ; 251
4fe: 7f 4f sbci r23, 0xFF ; 255
500: 80 e0 ldi r24, 0x00 ; 0
502: d9 dd rcall .-1102 ; 0xb6 <unsigned int pinConfigure<pin_configure_t, pin_configure_t, pin_configure_t>(unsigned char, pin_configure_t const&, pin_configure_t const&, pin_configure_t const&)>
pinConfigure(PIN_PA4, PIN_DIR_SET , PIN_INPUT_ENABLE, PIN_INVERT_ON);
504: c9 82 std Y+1, r12 ; 0x01
506: da 82 std Y+2, r13 ; 0x02
508: ab 82 std Y+3, r10 ; 0x03
50a: bc 82 std Y+4, r11 ; 0x04
50c: 0d 83 std Y+5, r16 ; 0x05
50e: 1e 83 std Y+6, r17 ; 0x06
510: 9e 01 movw r18, r28
512: 2f 5f subi r18, 0xFF ; 255
514: 3f 4f sbci r19, 0xFF ; 255
516: ae 01 movw r20, r28
518: 4d 5f subi r20, 0xFD ; 253
51a: 5f 4f sbci r21, 0xFF ; 255
51c: be 01 movw r22, r28
51e: 6b 5f subi r22, 0xFB ; 251
520: 7f 4f sbci r23, 0xFF ; 255
522: 80 e0 ldi r24, 0x00 ; 0
524: c8 dd rcall .-1136 ; 0xb6 <unsigned int pinConfigure<pin_configure_t, pin_configure_t, pin_configure_t>(unsigned char, pin_configure_t const&, pin_configure_t const&, pin_configure_t const&)>
pinConfigure(PIN_PA4, PIN_OUT_CLR , PIN_DIR_SET, PIN_INPUT_DISABLE);
526: e9 82 std Y+1, r14 ; 0x01
528: fa 82 std Y+2, r15 ; 0x02
52a: 0b 83 std Y+3, r16 ; 0x03
52c: 1c 83 std Y+4, r17 ; 0x04
52e: 6d 82 std Y+5, r6 ; 0x05
530: 7e 82 std Y+6, r7 ; 0x06
532: 9e 01 movw r18, r28
534: 2f 5f subi r18, 0xFF ; 255
536: 3f 4f sbci r19, 0xFF ; 255
538: ae 01 movw r20, r28
53a: 4d 5f subi r20, 0xFD ; 253
53c: 5f 4f sbci r21, 0xFF ; 255
53e: be 01 movw r22, r28
540: 6b 5f subi r22, 0xFB ; 251
542: 7f 4f sbci r23, 0xFF ; 255
544: 80 e0 ldi r24, 0x00 ; 0
546: b7 dd rcall .-1170 ; 0xb6 <unsigned int pinConfigure<pin_configure_t, pin_configure_t, pin_configure_t>(unsigned char, pin_configure_t const&, pin_configure_t const&, pin_configure_t const&)>
void pinConfigure(uint8_t pin, uint16_t pinconfig) {
check_valid_digital_pin(pin);
uint8_t bit_mask = digitalPinToBitMask(pin);
b8: fc 01 movw r30, r24
ba: ea 52 subi r30, 0x2A ; 42
bc: fd 47 sbci r31, 0x7D ; 125
be: 40 81 ld r20, Z
C:\arduino-1.8.13-portable\portable\packages\megaTinyCore\hardware\megaavr\2.5.4\cores\megatinycore/wiring_digital.c:54
if (bit_mask == NOT_A_PIN) {
c0: 4f 3f cpi r20, 0xFF ; 255
c2: 09 f4 brne .+2 ; 0xc6 <pinConfigure+0x10>
c4: 3f c0 rjmp .+126 ; 0x144 <__EEPROM_REGION_LENGTH__+0x44>
C:\arduino-1.8.13-portable\portable\packages\megaTinyCore\hardware\megaavr\2.5.4\cores\megatinycore/wiring_digital.c:57
return; /* ignore invalid pins passed at runtime */
}
volatile uint8_t *portbase = (volatile uint8_t*) digitalPinToPortStruct(pin);
c6: fc 01 movw r30, r24
c8: ec 53 subi r30, 0x3C ; 60
ca: fd 47 sbci r31, 0x7D ; 125
cc: e0 81 ld r30, Z
ce: 20 e2 ldi r18, 0x20 ; 32
d0: e2 9f mul r30, r18
d2: f0 01 movw r30, r0
d4: 11 24 eor r1, r1
d6: fc 5f subi r31, 0xFC ; 252
C:\arduino-1.8.13-portable\portable\packages\megaTinyCore\hardware\megaavr\2.5.4\cores\megatinycore/wiring_digital.c:58
uint8_t bit_pos = digitalPinToBitPosition(pin);
d8: 8e 54 subi r24, 0x4E ; 78
da: 9d 47 sbci r25, 0x7D ; 125
dc: dc 01 movw r26, r24
de: 8c 91 ld r24, X
C:\arduino-1.8.13-portable\portable\packages\megaTinyCore\hardware\megaavr\2.5.4\cores\megatinycore/wiring_digital.c:59
uint8_t setting = pinconfig & 0x03; // grab direction bits
e0: 96 2f mov r25, r22
e2: 93 70 andi r25, 0x03 ; 3
C:\arduino-1.8.13-portable\portable\packages\megaTinyCore\hardware\megaavr\2.5.4\cores\megatinycore/wiring_digital.c:60
if (setting) {
e4: 09 f0 breq .+2 ; 0xe8 <pinConfigure+0x32>
C:\arduino-1.8.13-portable\portable\packages\megaTinyCore\hardware\megaavr\2.5.4\cores\megatinycore/wiring_digital.c:61
*(portbase + setting) = bit_mask;
e6: 41 83 std Z+1, r20 ; 0x01
C:\arduino-1.8.13-portable\portable\packages\megaTinyCore\hardware\megaavr\2.5.4\cores\megatinycore/wiring_digital.c:63
}
pinconfig >>= 2;
e8: 9b 01 movw r18, r22
ea: 36 95 lsr r19
ec: 27 95 ror r18
ee: 36 95 lsr r19
f0: 27 95 ror r18
C:\arduino-1.8.13-portable\portable\packages\megaTinyCore\hardware\megaavr\2.5.4\cores\megatinycore/wiring_digital.c:64
setting = pinconfig & 0x03; // as above, only for output
f2: a2 2f mov r26, r18
f4: a3 70 andi r26, 0x03 ; 3
C:\arduino-1.8.13-portable\portable\packages\megaTinyCore\hardware\megaavr\2.5.4\cores\megatinycore/wiring_digital.c:65
if (setting) {
f6: 29 f0 breq .+10 ; 0x102 <__EEPROM_REGION_LENGTH__+0x2>
C:\arduino-1.8.13-portable\portable\packages\megaTinyCore\hardware\megaavr\2.5.4\cores\megatinycore/wiring_digital.c:66
*(portbase + 4 + setting) = bit_mask;
f8: b0 e0 ldi r27, 0x00 ; 0
fa: 14 96 adiw r26, 0x04 ; 4
fc: ae 0f add r26, r30
fe: bf 1f adc r27, r31
100: 4c 93 st X, r20
C:\arduino-1.8.13-portable\portable\packages\megaTinyCore\hardware\megaavr\2.5.4\cores\megatinycore/wiring_digital.c:68
}
if (!(pinconfig & 0x03FFC)) return;
102: 2c 7f andi r18, 0xFC ; 252
104: 3f 73 andi r19, 0x3F ; 63
106: 23 2b or r18, r19
108: e9 f0 breq .+58 ; 0x144 <__EEPROM_REGION_LENGTH__+0x44>
C:\arduino-1.8.13-portable\portable\packages\megaTinyCore\hardware\megaavr\2.5.4\cores\megatinycore/wiring_digital.c:69
pinconfig >>= 2;
10a: 9b 01 movw r18, r22
10c: 94 e0 ldi r25, 0x04 ; 4
10e: 36 95 lsr r19
110: 27 95 ror r18
112: 9a 95 dec r25
114: e1 f7 brne .-8 ; 0x10e <__EEPROM_REGION_LENGTH__+0xe>
C:\arduino-1.8.13-portable\portable\packages\megaTinyCore\hardware\megaavr\2.5.4\cores\megatinycore/wiring_digital.c:70
uint8_t oldSREG = SREG;
116: 4f b7 in r20, 0x3f ; 63
C:\arduino-1.8.13-portable\portable\packages\megaTinyCore\hardware\megaavr\2.5.4\cores\megatinycore/wiring_digital.c:71
cli();
118: f8 94 cli
C:\arduino-1.8.13-portable\portable\packages\megaTinyCore\hardware\megaavr\2.5.4\cores\megatinycore/wiring_digital.c:72
uint8_t pinncfg = *(portbase + 0x10 + bit_pos);
11a: 90 e0 ldi r25, 0x00 ; 0
11c: 40 96 adiw r24, 0x10 ; 16
11e: e8 0f add r30, r24
120: f9 1f adc r31, r25
122: 80 81 ld r24, Z
C:\arduino-1.8.13-portable\portable\packages\megaTinyCore\hardware\megaavr\2.5.4\cores\megatinycore/wiring_digital.c:73
if (pinconfig & 0x08) {
124: 23 ff sbrs r18, 3
126: 04 c0 rjmp .+8 ; 0x130 <__EEPROM_REGION_LENGTH__+0x30>
C:\arduino-1.8.13-portable\portable\packages\megaTinyCore\hardware\megaavr\2.5.4\cores\megatinycore/wiring_digital.c:74
pinncfg = (pinncfg & 0xF8) | (pinconfig & 0x07);
128: 88 7f andi r24, 0xF8 ; 248
12a: 92 2f mov r25, r18
12c: 97 70 andi r25, 0x07 ; 7
12e: 89 2b or r24, r25
C:\arduino-1.8.13-portable\portable\packages\megaTinyCore\hardware\megaavr\2.5.4\cores\megatinycore/wiring_digital.c:76
}
uint8_t temp = pinconfig & 0x30;
130: 20 73 andi r18, 0x30 ; 48
C:\arduino-1.8.13-portable\portable\packages\megaTinyCore\hardware\megaavr\2.5.4\cores\megatinycore/wiring_digital.c:77
if (temp) {
132: 09 f0 breq .+2 ; 0x136 <__EEPROM_REGION_LENGTH__+0x36>
C:\arduino-1.8.13-portable\portable\packages\megaTinyCore\hardware\megaavr\2.5.4\cores\megatinycore/wiring_digital.c:83
if (temp == 0x30) {
pinncfg ^= 0x08; // toggle pullup - of dubious utility
} else if (temp == 0x20) {
pinncfg &= ~(0x08); // clear
} else {
pinncfg |= 0x08; // set
134: 88 60 ori r24, 0x08 ; 8
C:\arduino-1.8.13-portable\portable\packages\megaTinyCore\hardware\megaavr\2.5.4\cores\megatinycore/wiring_digital.c:86
}
}
pinconfig >>= 8; // now it's just the last 4 bits.
136: 97 2f mov r25, r23
138: 92 95 swap r25
13a: 9f 70 andi r25, 0x0F ; 15
C:\arduino-1.8.13-portable\portable\packages\megaTinyCore\hardware\megaavr\2.5.4\cores\megatinycore/wiring_digital.c:115
pinncfg &= ~(0x40); // clear
}
}
#endif
temp = pinconfig & 0x0C;
if (temp) {
13c: 09 f0 breq .+2 ; 0x140 <__EEPROM_REGION_LENGTH__+0x40>
C:\arduino-1.8.13-portable\portable\packages\megaTinyCore\hardware\megaavr\2.5.4\cores\megatinycore/wiring_digital.c:121
if (temp == 0x0C) {
pinncfg ^= 0x80; // toggle invert - of dubious utility, but I'll accept it.
} else if (temp == 0x08) {
pinncfg &= ~(0x80); // clear
} else {
pinncfg |= 0x80; // set
13e: 80 68 ori r24, 0x80 ; 128
C:\arduino-1.8.13-portable\portable\packages\megaTinyCore\hardware\megaavr\2.5.4\cores\megatinycore/wiring_digital.c:124
}
}
*(portbase + 0x10 + bit_pos)=pinncfg;
140: 80 83 st Z, r24
C:\arduino-1.8.13-portable\portable\packages\megaTinyCore\hardware\megaavr\2.5.4\cores\megatinycore/wiring_digital.c:125
SREG = oldSREG; // re-enable interrupts
142: 4f bf out 0x3f, r20 ; 63
C:\arduino-1.8.13-portable\portable\packages\megaTinyCore\hardware\megaavr\2.5.4\cores\megatinycore/wiring_digital.c:126
}
144: 08 95 ret
vs
000000b6 <unsigned int pinConfigure<pin_configure_t, pin_configure_t, pin_configure_t>(unsigned char, pin_configure_t const&, pin_configure_t const&, pin_configure_t const&)>:
pinConfigure():
C:\Users\Spence\Documents\Arduino\hardware\megaTinyCore\megaavr\cores\megatinycore/Arduino.h:465
configure every pin parameter, both those configured through the PORTx
regiters and those that are configured through the PORTx.PINnCTRL register.
*/
template <typename MODE, typename... MODES>
uint16_t pinConfigure(const uint8_t digital_pin, const MODE& mode, const MODES&... modes)
b6: ff 92 push r15
b8: 0f 93 push r16
ba: 1f 93 push r17
bc: cf 93 push r28
be: df 93 push r29
C:\Users\Spence\Documents\Arduino\hardware\megaTinyCore\megaavr\cores\megatinycore/Arduino.h:468
{
// Or-ing together the arguments using recursion
uint16_t pin_config = mode | (pin_configure_t)pinConfigure(digital_pin, modes...);
c0: fb 01 movw r30, r22
c2: 00 81 ld r16, Z
c4: 11 81 ldd r17, Z+1 ; 0x01
C:\Users\Spence\Documents\Arduino\hardware\megaTinyCore\megaavr\cores\megatinycore/Arduino.h:470
uint8_t bit_mask = digitalPinToBitMask(digital_pin);
c6: 68 2f mov r22, r24
c8: 70 e0 ldi r23, 0x00 ; 0
ca: eb 01 movw r28, r22
cc: c8 5e subi r28, 0xE8 ; 232
ce: db 47 sbci r29, 0x7B ; 123
d0: 98 81 ld r25, Y
C:\Users\Spence\Documents\Arduino\hardware\megaTinyCore\megaavr\cores\megatinycore/Arduino.h:471
if(bit_mask == NOT_A_PIN || !pin_config) // Return if digital pin is invalid or the other parameters or out to zero
d2: 9f 3f cpi r25, 0xFF ; 255
d4: 09 f4 brne .+2 ; 0xd8 <unsigned int pinConfigure<pin_configure_t, pin_configure_t, pin_configure_t>(unsigned char, pin_configure_t const&, pin_configure_t const&, pin_configure_t const&)+0x22>
d6: 5b c0 rjmp .+182 ; 0x18e <__EEPROM_REGION_LENGTH__+0x8e>
C:\Users\Spence\Documents\Arduino\hardware\megaTinyCore\megaavr\cores\megatinycore/Arduino.h:468
template <typename MODE, typename... MODES>
uint16_t pinConfigure(const uint8_t digital_pin, const MODE& mode, const MODES&... modes)
{
// Or-ing together the arguments using recursion
uint16_t pin_config = mode | (pin_configure_t)pinConfigure(digital_pin, modes...);
d8: fa 01 movw r30, r20
da: 40 81 ld r20, Z
dc: 51 81 ldd r21, Z+1 ; 0x01
de: f9 01 movw r30, r18
e0: 20 81 ld r18, Z
e2: 31 81 ldd r19, Z+1 ; 0x01
e4: 24 2b or r18, r20
e6: 35 2b or r19, r21
C:\Users\Spence\Documents\Arduino\hardware\megaTinyCore\megaavr\cores\megatinycore/Arduino.h:471
uint8_t bit_mask = digitalPinToBitMask(digital_pin);
if(bit_mask == NOT_A_PIN || !pin_config) // Return if digital pin is invalid or the other parameters or out to zero
e8: 21 15 cp r18, r1
ea: 31 05 cpc r19, r1
ec: 09 f4 brne .+2 ; 0xf0 <unsigned int pinConfigure<pin_configure_t, pin_configure_t, pin_configure_t>(unsigned char, pin_configure_t const&, pin_configure_t const&, pin_configure_t const&)+0x3a>
ee: 6f c0 rjmp .+222 ; 0x1ce <__EEPROM_REGION_LENGTH__+0xce>
C:\Users\Spence\Documents\Arduino\hardware\megaTinyCore\megaavr\cores\megatinycore/Arduino.h:474
return 0;
uint8_t bit_pos = digitalPinToBitPosition(digital_pin);
f0: fb 01 movw r30, r22
f2: ee 5f subi r30, 0xFE ; 254
f4: fb 47 sbci r31, 0x7B ; 123
f6: 80 81 ld r24, Z
C:\Users\Spence\Documents\Arduino\hardware\megaTinyCore\megaavr\cores\megatinycore/Arduino.h:475
volatile uint8_t *portbase = (volatile uint8_t*) digitalPinToPortStruct(digital_pin);
f8: fb 01 movw r30, r22
fa: e4 51 subi r30, 0x14 ; 20
fc: fc 47 sbci r31, 0x7C ; 124
fe: e0 81 ld r30, Z
100: f0 e2 ldi r31, 0x20 ; 32
102: ef 9f mul r30, r31
104: a0 01 movw r20, r0
106: 11 24 eor r1, r1
108: 5c 5f subi r21, 0xFC ; 252
C:\Users\Spence\Documents\Arduino\hardware\megaTinyCore\megaavr\cores\megatinycore/Arduino.h:478
// Write to selected pin direction register
uint8_t setting = pin_config & 0x03; // Mask out direction bits (DIR, DIRSET, DIRCLR, DIRTGL)
10a: e2 2f mov r30, r18
10c: e3 70 andi r30, 0x03 ; 3
C:\Users\Spence\Documents\Arduino\hardware\megaTinyCore\megaavr\cores\megatinycore/Arduino.h:479
if(setting)
10e: 21 f0 breq .+8 ; 0x118 <__EEPROM_REGION_LENGTH__+0x18>
C:\Users\Spence\Documents\Arduino\hardware\megaTinyCore\megaavr\cores\megatinycore/Arduino.h:480
*(portbase + setting) = bit_mask;
110: e4 0f add r30, r20
112: f5 2f mov r31, r21
114: f1 1d adc r31, r1
116: 90 83 st Z, r25
C:\Users\Spence\Documents\Arduino\hardware\megaTinyCore\megaavr\cores\megatinycore/Arduino.h:483
// Write to selected output register
pin_config >>= 2;
118: f9 01 movw r30, r18
11a: f6 95 lsr r31
11c: e7 95 ror r30
11e: f6 95 lsr r31
120: e7 95 ror r30
C:\Users\Spence\Documents\Arduino\hardware\megaTinyCore\megaavr\cores\megatinycore/Arduino.h:484
setting = pin_config & 0x03;
122: ae 2f mov r26, r30
124: a3 70 andi r26, 0x03 ; 3
C:\Users\Spence\Documents\Arduino\hardware\megaTinyCore\megaavr\cores\megatinycore/Arduino.h:485
if(setting)
126: 29 f0 breq .+10 ; 0x132 <__EEPROM_REGION_LENGTH__+0x32>
C:\Users\Spence\Documents\Arduino\hardware\megaTinyCore\megaavr\cores\megatinycore/Arduino.h:486
*(portbase + 4 + setting) = bit_mask;
128: b0 e0 ldi r27, 0x00 ; 0
12a: 14 96 adiw r26, 0x04 ; 4
12c: a4 0f add r26, r20
12e: b5 1f adc r27, r21
130: 9c 93 st X, r25
C:\Users\Spence\Documents\Arduino\hardware\megaTinyCore\megaavr\cores\megatinycore/Arduino.h:489
// Return if there is nothing more to configure
if(!(pin_config & 0x3FFC))
132: ec 7f andi r30, 0xFC ; 252
134: ff 73 andi r31, 0x3F ; 63
136: ef 2b or r30, r31
138: 09 f4 brne .+2 ; 0x13c <__EEPROM_REGION_LENGTH__+0x3c>
13a: 49 c0 rjmp .+146 ; 0x1ce <__EEPROM_REGION_LENGTH__+0xce>
C:\Users\Spence\Documents\Arduino\hardware\megaTinyCore\megaavr\cores\megatinycore/Arduino.h:492
return 0;
uint8_t oldSREG = SREG; // Store SREG
13c: ff b6 in r15, 0x3f ; 63
C:\Users\Spence\Documents\Arduino\hardware\megaTinyCore\megaavr\cores\megatinycore/Arduino.h:493
cli(); // Disable interrupts
13e: f8 94 cli
C:\Users\Spence\Documents\Arduino\hardware\megaTinyCore\megaavr\cores\megatinycore/Arduino.h:496
// PINnCTRL register
pin_config >>= 2;
140: d9 01 movw r26, r18
142: 94 e0 ldi r25, 0x04 ; 4
144: b6 95 lsr r27
146: a7 95 ror r26
148: 9a 95 dec r25
14a: e1 f7 brne .-8 ; 0x144 <__EEPROM_REGION_LENGTH__+0x44>
C:\Users\Spence\Documents\Arduino\hardware\megaTinyCore\megaavr\cores\megatinycore/Arduino.h:497
uint8_t pinncfg = *(portbase + 0x10 + bit_pos);
14c: e8 2f mov r30, r24
14e: f0 e0 ldi r31, 0x00 ; 0
150: 70 96 adiw r30, 0x10 ; 16
152: e4 0f add r30, r20
154: f5 1f adc r31, r21
156: 90 81 ld r25, Z
C:\Users\Spence\Documents\Arduino\hardware\megaTinyCore\megaavr\cores\megatinycore/Arduino.h:499
// Input sense configuration (ISC)
if(pin_config & 0x08)
158: a3 ff sbrs r26, 3
15a: 04 c0 rjmp .+8 ; 0x164 <__EEPROM_REGION_LENGTH__+0x64>
C:\Users\Spence\Documents\Arduino\hardware\megaTinyCore\megaavr\cores\megatinycore/Arduino.h:500
pinncfg = (pinncfg & 0xF8) | (pin_config & PORT_ISC_gm);
15c: 98 7f andi r25, 0xF8 ; 248
15e: 8a 2f mov r24, r26
160: 87 70 andi r24, 0x07 ; 7
162: 98 2b or r25, r24
C:\Users\Spence\Documents\Arduino\hardware\megaTinyCore\megaavr\cores\megatinycore/Arduino.h:502
// Pullup resistor
uint8_t temp = pin_config & 0x30;
164: a0 73 andi r26, 0x30 ; 48
C:\Users\Spence\Documents\Arduino\hardware\megaTinyCore\megaavr\cores\megatinycore/Arduino.h:503
if(temp)
166: 21 f0 breq .+8 ; 0x170 <__EEPROM_REGION_LENGTH__+0x70>
C:\Users\Spence\Documents\Arduino\hardware\megaTinyCore\megaavr\cores\megatinycore/Arduino.h:505
{
if(temp == 0x30)
168: a0 33 cpi r26, 0x30 ; 48
16a: c9 f4 brne .+50 ; 0x19e <__EEPROM_REGION_LENGTH__+0x9e>
C:\Users\Spence\Documents\Arduino\hardware\megaTinyCore\megaavr\cores\megatinycore/Arduino.h:506
pinncfg ^= PORT_PULLUPEN_bm; // Toggle pullup
16c: 88 e0 ldi r24, 0x08 ; 8
16e: 98 27 eor r25, r24
C:\Users\Spence\Documents\Arduino\hardware\megaTinyCore\megaavr\cores\megatinycore/Arduino.h:513
pinncfg &= ~(PORT_PULLUPEN_bm); // Clear pullup
else
pinncfg |= PORT_PULLUPEN_bm; // Set pullup
}
// Invert pin
pin_config >>= 8;
170: 23 2f mov r18, r19
172: 33 27 eor r19, r19
174: 22 95 swap r18
176: 2f 70 andi r18, 0x0F ; 15
C:\Users\Spence\Documents\Arduino\hardware\megaTinyCore\megaavr\cores\megatinycore/Arduino.h:514
temp = pin_config & 0x0C;
178: 82 2f mov r24, r18
17a: 8c 70 andi r24, 0x0C ; 12
C:\Users\Spence\Documents\Arduino\hardware\megaTinyCore\megaavr\cores\megatinycore/Arduino.h:515
if(temp)
17c: 19 f0 breq .+6 ; 0x184 <__EEPROM_REGION_LENGTH__+0x84>
C:\Users\Spence\Documents\Arduino\hardware\megaTinyCore\megaavr\cores\megatinycore/Arduino.h:517
{
if(temp == 0x0C)
17e: 8c 30 cpi r24, 0x0C ; 12
180: a1 f4 brne .+40 ; 0x1aa <__EEPROM_REGION_LENGTH__+0xaa>
C:\Users\Spence\Documents\Arduino\hardware\megaTinyCore\megaavr\cores\megatinycore/Arduino.h:518
pinncfg ^= PORT_INVEN_bm; // Toggle invert
182: 90 58 subi r25, 0x80 ; 128
C:\Users\Spence\Documents\Arduino\hardware\megaTinyCore\megaavr\cores\megatinycore/Arduino.h:525
pinncfg &= ~(PORT_INVEN_bm); // Clear
else
pinncfg |= PORT_INVEN_bm; // Set
}
// Write to PINnCTRL register
*(portbase + 0x10 + bit_pos) = pinncfg;
184: 90 83 st Z, r25
C:\Users\Spence\Documents\Arduino\hardware\megaTinyCore\megaavr\cores\megatinycore/Arduino.h:528
// Restore SREG
SREG = oldSREG;
186: ff be out 0x3f, r15 ; 63
C:\Users\Spence\Documents\Arduino\hardware\megaTinyCore\megaavr\cores\megatinycore/Arduino.h:470
uint16_t pinConfigure(const uint8_t digital_pin, const MODE& mode, const MODES&... modes)
{
// Or-ing together the arguments using recursion
uint16_t pin_config = mode | (pin_configure_t)pinConfigure(digital_pin, modes...);
uint8_t bit_mask = digitalPinToBitMask(digital_pin);
188: 48 81 ld r20, Y
C:\Users\Spence\Documents\Arduino\hardware\megaTinyCore\megaavr\cores\megatinycore/Arduino.h:471
if(bit_mask == NOT_A_PIN || !pin_config) // Return if digital pin is invalid or the other parameters or out to zero
18a: 4f 3f cpi r20, 0xFF ; 255
18c: 19 f5 brne .+70 ; 0x1d4 <__EEPROM_REGION_LENGTH__+0xd4>
C:\Users\Spence\Documents\Arduino\hardware\megaTinyCore\megaavr\cores\megatinycore/Arduino.h:472
return 0;
18e: 80 e0 ldi r24, 0x00 ; 0
C:\Users\Spence\Documents\Arduino\hardware\megaTinyCore\megaavr\cores\megatinycore/Arduino.h:531
// Restore SREG
SREG = oldSREG;
return pin_config;
}
190: 90 e0 ldi r25, 0x00 ; 0
192: df 91 pop r29
194: cf 91 pop r28
196: 1f 91 pop r17
198: 0f 91 pop r16
19a: ff 90 pop r15
19c: 08 95 ret
C:\Users\Spence\Documents\Arduino\hardware\megaTinyCore\megaavr\cores\megatinycore/Arduino.h:507
uint8_t temp = pin_config & 0x30;
if(temp)
{
if(temp == 0x30)
pinncfg ^= PORT_PULLUPEN_bm; // Toggle pullup
else if(temp == 0x20)
19e: a0 32 cpi r26, 0x20 ; 32
1a0: 11 f4 brne .+4 ; 0x1a6 <__EEPROM_REGION_LENGTH__+0xa6>
C:\Users\Spence\Documents\Arduino\hardware\megaTinyCore\megaavr\cores\megatinycore/Arduino.h:508
pinncfg &= ~(PORT_PULLUPEN_bm); // Clear pullup
1a2: 97 7f andi r25, 0xF7 ; 247
1a4: e5 cf rjmp .-54 ; 0x170 <__EEPROM_REGION_LENGTH__+0x70>
C:\Users\Spence\Documents\Arduino\hardware\megaTinyCore\megaavr\cores\megatinycore/Arduino.h:510
else
pinncfg |= PORT_PULLUPEN_bm; // Set pullup
1a6: 98 60 ori r25, 0x08 ; 8
1a8: e3 cf rjmp .-58 ; 0x170 <__EEPROM_REGION_LENGTH__+0x70>
C:\Users\Spence\Documents\Arduino\hardware\megaTinyCore\megaavr\cores\megatinycore/Arduino.h:519
temp = pin_config & 0x0C;
if(temp)
{
if(temp == 0x0C)
pinncfg ^= PORT_INVEN_bm; // Toggle invert
else if(temp == 0x08)
1aa: 88 30 cpi r24, 0x08 ; 8
1ac: 11 f4 brne .+4 ; 0x1b2 <__EEPROM_REGION_LENGTH__+0xb2>
C:\Users\Spence\Documents\Arduino\hardware\megaTinyCore\megaavr\cores\megatinycore/Arduino.h:520
pinncfg &= ~(PORT_INVEN_bm); // Clear
1ae: 9f 77 andi r25, 0x7F ; 127
1b0: e9 cf rjmp .-46 ; 0x184 <__EEPROM_REGION_LENGTH__+0x84>
C:\Users\Spence\Documents\Arduino\hardware\megaTinyCore\megaavr\cores\megatinycore/Arduino.h:522
else
pinncfg |= PORT_INVEN_bm; // Set
1b2: 90 68 ori r25, 0x80 ; 128
1b4: e7 cf rjmp .-50 ; 0x184 <__EEPROM_REGION_LENGTH__+0x84>
C:\Users\Spence\Documents\Arduino\hardware\megaTinyCore\megaavr\cores\megatinycore/Arduino.h:507
uint8_t temp = pin_config & 0x30;
if(temp)
{
if(temp == 0x30)
pinncfg ^= PORT_PULLUPEN_bm; // Toggle pullup
else if(temp == 0x20)
1b6: 40 32 cpi r20, 0x20 ; 32
1b8: 11 f4 brne .+4 ; 0x1be <__EEPROM_REGION_LENGTH__+0xbe>
C:\Users\Spence\Documents\Arduino\hardware\megaTinyCore\megaavr\cores\megatinycore/Arduino.h:508
pinncfg &= ~(PORT_PULLUPEN_bm); // Clear pullup
1ba: 97 7f andi r25, 0xF7 ; 247
1bc: 51 c0 rjmp .+162 ; 0x260 <__EEPROM_REGION_LENGTH__+0x160>
C:\Users\Spence\Documents\Arduino\hardware\megaTinyCore\megaavr\cores\megatinycore/Arduino.h:510
else
pinncfg |= PORT_PULLUPEN_bm; // Set pullup
1be: 98 60 ori r25, 0x08 ; 8
1c0: 4f c0 rjmp .+158 ; 0x260 <__EEPROM_REGION_LENGTH__+0x160>
C:\Users\Spence\Documents\Arduino\hardware\megaTinyCore\megaavr\cores\megatinycore/Arduino.h:519
temp = pin_config & 0x0C;
if(temp)
{
if(temp == 0x0C)
pinncfg ^= PORT_INVEN_bm; // Toggle invert
else if(temp == 0x08)
1c2: 28 30 cpi r18, 0x08 ; 8
1c4: 11 f4 brne .+4 ; 0x1ca <__EEPROM_REGION_LENGTH__+0xca>
C:\Users\Spence\Documents\Arduino\hardware\megaTinyCore\megaavr\cores\megatinycore/Arduino.h:520
pinncfg &= ~(PORT_INVEN_bm); // Clear
1c6: 9f 77 andi r25, 0x7F ; 127
1c8: 55 c0 rjmp .+170 ; 0x274 <__EEPROM_REGION_LENGTH__+0x174>
C:\Users\Spence\Documents\Arduino\hardware\megaTinyCore\megaavr\cores\megatinycore/Arduino.h:522
else
pinncfg |= PORT_INVEN_bm; // Set
1ca: 90 68 ori r25, 0x80 ; 128
1cc: 53 c0 rjmp .+166 ; 0x274 <__EEPROM_REGION_LENGTH__+0x174>
C:\Users\Spence\Documents\Arduino\hardware\megaTinyCore\megaavr\cores\megatinycore/Arduino.h:470
uint16_t pinConfigure(const uint8_t digital_pin, const MODE& mode, const MODES&... modes)
{
// Or-ing together the arguments using recursion
uint16_t pin_config = mode | (pin_configure_t)pinConfigure(digital_pin, modes...);
uint8_t bit_mask = digitalPinToBitMask(digital_pin);
1ce: 48 81 ld r20, Y
C:\Users\Spence\Documents\Arduino\hardware\megaTinyCore\megaavr\cores\megatinycore/Arduino.h:472
if(bit_mask == NOT_A_PIN || !pin_config) // Return if digital pin is invalid or the other parameters or out to zero
return 0;
1d0: 30 e0 ldi r19, 0x00 ; 0
1d2: 20 e0 ldi r18, 0x00 ; 0
C:\Users\Spence\Documents\Arduino\hardware\megaTinyCore\megaavr\cores\megatinycore/Arduino.h:468
template <typename MODE, typename... MODES>
uint16_t pinConfigure(const uint8_t digital_pin, const MODE& mode, const MODES&... modes)
{
// Or-ing together the arguments using recursion
uint16_t pin_config = mode | (pin_configure_t)pinConfigure(digital_pin, modes...);
1d4: 20 2b or r18, r16
1d6: 31 2b or r19, r17
C:\Users\Spence\Documents\Arduino\hardware\megaTinyCore\megaavr\cores\megatinycore/Arduino.h:471
uint8_t bit_mask = digitalPinToBitMask(digital_pin);
if(bit_mask == NOT_A_PIN || !pin_config) // Return if digital pin is invalid or the other parameters or out to zero
1d8: 21 15 cp r18, r1
1da: 31 05 cpc r19, r1
1dc: c1 f2 breq .-80 ; 0x18e <__EEPROM_REGION_LENGTH__+0x8e>
C:\Users\Spence\Documents\Arduino\hardware\megaTinyCore\megaavr\cores\megatinycore/Arduino.h:474
return 0;
uint8_t bit_pos = digitalPinToBitPosition(digital_pin);
1de: fb 01 movw r30, r22
1e0: ee 5f subi r30, 0xFE ; 254
1e2: fb 47 sbci r31, 0x7B ; 123
1e4: a0 81 ld r26, Z
C:\Users\Spence\Documents\Arduino\hardware\megaTinyCore\megaavr\cores\megatinycore/Arduino.h:475
volatile uint8_t *portbase = (volatile uint8_t*) digitalPinToPortStruct(digital_pin);
1e6: 64 51 subi r22, 0x14 ; 20
1e8: 7c 47 sbci r23, 0x7C ; 124
1ea: fb 01 movw r30, r22
1ec: 80 81 ld r24, Z
1ee: f0 e2 ldi r31, 0x20 ; 32
1f0: 8f 9f mul r24, r31
1f2: c0 01 movw r24, r0
1f4: 11 24 eor r1, r1
1f6: 9c 5f subi r25, 0xFC ; 252
C:\Users\Spence\Documents\Arduino\hardware\megaTinyCore\megaavr\cores\megatinycore/Arduino.h:478
// Write to selected pin direction register
uint8_t setting = pin_config & 0x03; // Mask out direction bits (DIR, DIRSET, DIRCLR, DIRTGL)
1f8: e2 2f mov r30, r18
1fa: e3 70 andi r30, 0x03 ; 3
C:\Users\Spence\Documents\Arduino\hardware\megaTinyCore\megaavr\cores\megatinycore/Arduino.h:479
if(setting)
1fc: 21 f0 breq .+8 ; 0x206 <__EEPROM_REGION_LENGTH__+0x106>
C:\Users\Spence\Documents\Arduino\hardware\megaTinyCore\megaavr\cores\megatinycore/Arduino.h:480
*(portbase + setting) = bit_mask;
1fe: e8 0f add r30, r24
200: f9 2f mov r31, r25
202: f1 1d adc r31, r1
204: 40 83 st Z, r20
C:\Users\Spence\Documents\Arduino\hardware\megaTinyCore\megaavr\cores\megatinycore/Arduino.h:483
// Write to selected output register
pin_config >>= 2;
206: b9 01 movw r22, r18
208: 76 95 lsr r23
20a: 67 95 ror r22
20c: 76 95 lsr r23
20e: 67 95 ror r22
C:\Users\Spence\Documents\Arduino\hardware\megaTinyCore\megaavr\cores\megatinycore/Arduino.h:484
setting = pin_config & 0x03;
210: e6 2f mov r30, r22
212: e3 70 andi r30, 0x03 ; 3
C:\Users\Spence\Documents\Arduino\hardware\megaTinyCore\megaavr\cores\megatinycore/Arduino.h:485
if(setting)
214: 29 f0 breq .+10 ; 0x220 <__EEPROM_REGION_LENGTH__+0x120>
C:\Users\Spence\Documents\Arduino\hardware\megaTinyCore\megaavr\cores\megatinycore/Arduino.h:486
*(portbase + 4 + setting) = bit_mask;
216: f0 e0 ldi r31, 0x00 ; 0
218: 34 96 adiw r30, 0x04 ; 4
21a: e8 0f add r30, r24
21c: f9 1f adc r31, r25
21e: 40 83 st Z, r20
C:\Users\Spence\Documents\Arduino\hardware\megaTinyCore\megaavr\cores\megatinycore/Arduino.h:489
// Return if there is nothing more to configure
if(!(pin_config & 0x3FFC))
220: 6c 7f andi r22, 0xFC ; 252
222: 7f 73 andi r23, 0x3F ; 63
224: 67 2b or r22, r23
226: 09 f4 brne .+2 ; 0x22a <__EEPROM_REGION_LENGTH__+0x12a>
228: b2 cf rjmp .-156 ; 0x18e <__EEPROM_REGION_LENGTH__+0x8e>
C:\Users\Spence\Documents\Arduino\hardware\megaTinyCore\megaavr\cores\megatinycore/Arduino.h:492
return 0;
uint8_t oldSREG = SREG; // Store SREG
22a: 6f b7 in r22, 0x3f ; 63
C:\Users\Spence\Documents\Arduino\hardware\megaTinyCore\megaavr\cores\megatinycore/Arduino.h:493
cli(); // Disable interrupts
22c: f8 94 cli
C:\Users\Spence\Documents\Arduino\hardware\megaTinyCore\megaavr\cores\megatinycore/Arduino.h:496
// PINnCTRL register
pin_config >>= 2;
22e: a9 01 movw r20, r18
230: 24 e0 ldi r18, 0x04 ; 4
232: 56 95 lsr r21
234: 47 95 ror r20
236: 2a 95 dec r18
238: e1 f7 brne .-8 ; 0x232 <__EEPROM_REGION_LENGTH__+0x132>
C:\Users\Spence\Documents\Arduino\hardware\megaTinyCore\megaavr\cores\megatinycore/Arduino.h:497
uint8_t pinncfg = *(portbase + 0x10 + bit_pos);
23a: ea 2f mov r30, r26
23c: f0 e0 ldi r31, 0x00 ; 0
23e: 70 96 adiw r30, 0x10 ; 16
240: e8 0f add r30, r24
242: f9 1f adc r31, r25
244: 90 81 ld r25, Z
C:\Users\Spence\Documents\Arduino\hardware\megaTinyCore\megaavr\cores\megatinycore/Arduino.h:499
// Input sense configuration (ISC)
if(pin_config & 0x08)
246: 43 ff sbrs r20, 3
248: 04 c0 rjmp .+8 ; 0x252 <__EEPROM_REGION_LENGTH__+0x152>
C:\Users\Spence\Documents\Arduino\hardware\megaTinyCore\megaavr\cores\megatinycore/Arduino.h:500
pinncfg = (pinncfg & 0xF8) | (pin_config & PORT_ISC_gm);
24a: 98 7f andi r25, 0xF8 ; 248
24c: 84 2f mov r24, r20
24e: 87 70 andi r24, 0x07 ; 7
250: 98 2b or r25, r24
C:\Users\Spence\Documents\Arduino\hardware\megaTinyCore\megaavr\cores\megatinycore/Arduino.h:502
// Pullup resistor
uint8_t temp = pin_config & 0x30;
252: 40 73 andi r20, 0x30 ; 48
C:\Users\Spence\Documents\Arduino\hardware\megaTinyCore\megaavr\cores\megatinycore/Arduino.h:503
if(temp)
254: 29 f0 breq .+10 ; 0x260 <__EEPROM_REGION_LENGTH__+0x160>
C:\Users\Spence\Documents\Arduino\hardware\megaTinyCore\megaavr\cores\megatinycore/Arduino.h:505
{
if(temp == 0x30)
256: 40 33 cpi r20, 0x30 ; 48
258: 09 f0 breq .+2 ; 0x25c <__EEPROM_REGION_LENGTH__+0x15c>
25a: ad cf rjmp .-166 ; 0x1b6 <__EEPROM_REGION_LENGTH__+0xb6>
C:\Users\Spence\Documents\Arduino\hardware\megaTinyCore\megaavr\cores\megatinycore/Arduino.h:506
pinncfg ^= PORT_PULLUPEN_bm; // Toggle pullup
25c: 88 e0 ldi r24, 0x08 ; 8
25e: 98 27 eor r25, r24
C:\Users\Spence\Documents\Arduino\hardware\megaTinyCore\megaavr\cores\megatinycore/Arduino.h:513
pinncfg &= ~(PORT_PULLUPEN_bm); // Clear pullup
else
pinncfg |= PORT_PULLUPEN_bm; // Set pullup
}
// Invert pin
pin_config >>= 8;
260: 83 2f mov r24, r19
262: 82 95 swap r24
264: 8f 70 andi r24, 0x0F ; 15
C:\Users\Spence\Documents\Arduino\hardware\megaTinyCore\megaavr\cores\megatinycore/Arduino.h:514
temp = pin_config & 0x0C;
266: 28 2f mov r18, r24
268: 2c 70 andi r18, 0x0C ; 12
C:\Users\Spence\Documents\Arduino\hardware\megaTinyCore\megaavr\cores\megatinycore/Arduino.h:515
if(temp)
26a: 21 f0 breq .+8 ; 0x274 <__EEPROM_REGION_LENGTH__+0x174>
C:\Users\Spence\Documents\Arduino\hardware\megaTinyCore\megaavr\cores\megatinycore/Arduino.h:517
{
if(temp == 0x0C)
26c: 2c 30 cpi r18, 0x0C ; 12
26e: 09 f0 breq .+2 ; 0x272 <__EEPROM_REGION_LENGTH__+0x172>
270: a8 cf rjmp .-176 ; 0x1c2 <__EEPROM_REGION_LENGTH__+0xc2>
C:\Users\Spence\Documents\Arduino\hardware\megaTinyCore\megaavr\cores\megatinycore/Arduino.h:518
pinncfg ^= PORT_INVEN_bm; // Toggle invert
272: 90 58 subi r25, 0x80 ; 128
C:\Users\Spence\Documents\Arduino\hardware\megaTinyCore\megaavr\cores\megatinycore/Arduino.h:525
pinncfg &= ~(PORT_INVEN_bm); // Clear
else
pinncfg |= PORT_INVEN_bm; // Set
}
// Write to PINnCTRL register
*(portbase + 0x10 + bit_pos) = pinncfg;
274: 90 83 st Z, r25
C:\Users\Spence\Documents\Arduino\hardware\megaTinyCore\megaavr\cores\megatinycore/Arduino.h:528
// Restore SREG
SREG = oldSREG;
276: 6f bf out 0x3f, r22 ; 63
278: 8b cf rjmp .-234 ; 0x190 <__EEPROM_REGION_LENGTH__+0x90>
What is very clear is that stuff is being done at runtime that should be getting done at compile time.
Ok, I figured it out. The compiler wasn't able to figure out what was going on when the template function called itself. It usually can, but for some reason, not in this case. Fixed now.
https://github.com/MCUdude/MegaCoreX/commit/854d9e1041bef33e3bc50458f5efa686ab5118ec#diff-3425c70d2b78d865cd401a9c605f563eda19ce9cf9d095e63d5770d06423c949
Hi, Let me show you my Pin Lib. AVRxDB_Pin.zip
I forget where I was on the MCUDude implementation, The last thing I remember, things had been improvedm but there was still a substantial overhead, which matters since pinConfigure gets ported to megaTinyCore where it's serving parts with 2k of flash). But I've owed the classic tiny people a release for too long, ATTinyCore 2.0.0 goes out next.
Hi, Let me show you my Pin Lib. AVRxDB_Pin.zip
What's the overhead like?
No overhead, small "footprint". Do you have a standard code to compare? Make led blink or something similar. The difference is that I work with objects and their methods. Everything is compiled at compile time.
Sorry for not saying more here sooner. Basically, I can't pull in the code in the condition it is in. I was testing it on megaTinyCore, and the impact on codesize is catastrophic, and renders it unusable on some of the target platforms.
It appears that the attempts mafr have still been unsuccessful at making sure the ORing always happens at compile time if at all possible.
I am not qualified to rectify this myself; but I was wondering - would it make a difference if the variadic function was replaced with a macro? Wouldn't that get us to the point where, with compiletime constant values, a series of comma separated values could be made to shake out into a series of values separated by bitwise OR operators? Then any compiletime known ones would get constant folding applied; , and if they included things that weren't constant, it would still fold to the greatest extent possible, and it would never be bitwise or-ing compiletime constant values at runtime.
I love the improved syntax of pinConfigure(pin,option1,option2,option3) (in fact,I really hate the syntax I was forced to use!). And, from a logical or complexity stantpoint it make no sense that it couldn't be done - somehow., I see no reason that can't compile to something just as small. Except thathat the implementations we've been able to come up with don't. But I'm pretty useless at this because it's all aspects of the language that I don't really understand. As I've often remarked, I don't know C++, I know C and Assembly.
I guess you'd also have the same non-macro function that my implementation uses, which took only a single option argument that is the bitwise combination of the desirerd options, and that's what everything else would condense down to....
@mikrocoder - there are a few reasons I don't really like that code. None of them are technical.
The first thing is, it is not in keeping with the style of Arduino. Every other Arduino function to work with a pin is structured as functionName(pin,options) - a function takes a pin identifier and options (if any) and does something.
Second, - It's greek to me, I don't understand it very well.
Third - I still worry if one tried to use if on a larger scale, you'd suddenly find that under some situation, constant folding failed, with catastrophic size and performance effects. The optimizer isn't much better with C++ than I am. For example, classes sem to compltely disable most optimization. If you try to guard Serial.begin() against illegal compiletime known values by doimg
if (__builtin_constant_p(baud)) {
if (baud > maxbaud || baud < minbaud) {
badArg("The requested baud cannot be generated at this clock speed");
}
}
(which is what I tried shortly after discovering that technique) It doesn't work. Because it's a class method. even though it's only called once with an integer literal argment, the baud rate is never treated as a compile known constant! C++ feaures appear to be kryptonite to the optimizer, and with flash space and memory at such a premium on the smaller devices, something that makes the code more "modern and object porented-like" at the expense of compiled binary size is not an improvement. Anything I do that increases compile size is something I really think about whether I can justify it, particularly if it might get ported to megaTinyCore which serves 2k parts/
In the case of a the automatic clearing of the reset flags and stashing of them in GPIOR0 at startup. I nearly didn't make that the default behavior. But as I considered what the consequences of not doing that were, it was clear since, no matter what I wrote, 95% of users wouldn't follow my copy-paste instructions to ensure reset flags were cleared after every startup. And the problem with that it prevents the chip from detecting tat it just experienced a "dirty reset". hence all expectations of init() and all api functions were violated, we might even be in a state where CPUINT considers us to be in an interrupt and so won't execute any ISRs but we're executing normal code. If execution ever got to 0x0000, it is guaranteed that the code has malfunction, and it is highly likely that doing anthing other than an immediate software reset is unlikely to restore any approximation of functioning, and could result in arbitrary incorrect behavior. I further realized that dirty resets are liekly the main cause of AVRs getting into a "bad state" amd requiring a manual reset to revive. In light of the magnitude of the problems that it would preempt, I decided it would be irresponsible of me to know how to catch that case and not use it by default.
But support for alt pins with analogWrite? That's in DxCore, but I decided I couldn't justify porting to megaTinyCore.
There are a number of cases where I got most of the way through implemening some new feature, and started thinking about whether the usefulness justified the flash cost, decided it did not, and removed it.
Sorry for not saying more here sooner. Basically, I can't pull in the code in the condition it is in. I was testing it on megaTinyCore, and the impact on codesize is catastrophic, and renders it unusable on some of the target platforms.
It's been a while, and I don't remember all the details, but if you have a look at the current MegaCoreX pinConfigure implementation, this is able to OR together the parameters at compile time, and is just as small as your implementation with no overhead. The trick was to move the entire OR logic template out of the pinConfigure template.
Well, I have to apologize. I'm rather emvbarassed. I re-ran the tests with the version I'd put into megaTinyCore. The results did not match my notes at all .
Sometimes your implementation. wins and sometimes mine does... What is really interesting tough?
If you use the grammar for my version, with your implementation, the result is the worst of all!!
So please disregard ,my inaccrate objections.
I will release the next version, then merge this in.to master and then we can see whether people find problemswith it.
Thanks and sorry for bot the long delay an inaccrate claims;
Hello,
our approaches are just different. :wink: Everyone can handle this as they wish. In any case, I would like to get away from the define macro programming. The risk for errors is too high. I just wanted to show it. It's okay if you don't like it. It's just OOP.
I don't like these multi functions with hundreds of parameters. That is also very error prone. One typo and a pin is misconfigured without the compiler can complain. Or a pin is changed at another place unintentionally. You can overwrite anything with anything.
You can handle this as you like. :wink:
Hi,
you know what's funny now. I'm testing the Logic and Event examples right now because of deprecated warnings. That's what you wanted me to test. You don't like my pin classes. But the event class is okay? :smile: And with Logic the Arduino user should suddenly deal directly with hardware accesses. That makes your rejection a bit contradictory. :wink:
Those libraries are written in a very different style than they would be if I had written them. - they were by @MCUdude - I always find it striking how in some ways we are driven to the same thing - universal cores for all the decent arduino parts, chp-centric rather than board-centric, etc etc - and et, our tastes in coding style could hardly be more different than they are. The most recent version of the event library was the product of considerable debate, the sort of debate where, at t's heart, the disagreement is on what that goal should be.
For a great example of what happened when neither of us were aware of the others work, compare the Flash library in DxCore (which I wrote) with the one in megaTinyCore (which he wrote).
Specifically on event, there is a desperate need to have some form of abstraction hat is vaguely usablel; and he had a better idea of how to do it that I did.
The Ex-series is going to need a considerable amount of work there by the way, - the are changing up how pin and PIT events work. (The end goal, I think, is to make all channels the same. Actually, that is what they've done) but that obviously means some major changes are going to be needed in Event. A close examination of the ATPACK will reveal basically all there is to know about them - adapting Event to it... a little less straightforward, because we have gone from a setting in one place fully defining the event configuration for a given generator channel, to having the two event generators for each port configured in the PORT register, and the event generator pointed to one of those.
He also did Comparator, ZCD, and OPAMP libaries.. Without which there wouldn't be wrappers aroundthat funcrionalty at all. The key difference is that without his libraries, there was no wrapper around these things. I don't object to your library existing, but I'd need to do a lot of of work if I was to integrate it with the cores, just to to port it across megaTinyCore and DxCore to all parts, and it's functionality that already exists.through standard API functions.
This matter is a lower priority than:
- Getting serial to work which is a prerequisite for
- Getting timekeeping to work
- Bootloader must be fixed
- Getting holes to be handled in SerialUPDI
- Comparator and ZCD are hosed. I think I understand the former, I do not understand the latter issue,
- pinout diagrams, which I thinkwe have in a PR
- Merging and proofreading the platform IO docs Thus this quality of life chance is deferred to 1.5.x
If it is determined that the arguments cannot be combined at runtime, resulting in a grotesque expansion of the code, this change will not be made. If it possible without bloat, which it should be, the comma syntax is immeasurably superior and far more natural that what I came up with, and would be worth a moderate amount of development time - especially considering that, for the case if a pin known to not be outputting PWM, but which could, pinConfigure is faster than digitalWrite....
How strange! With only one or two calls to pinConfigure, or with lots of calls to it, the commas compile significantly smaller. In the 3-6 call range though, if they're all bitwise OR's, they come out smaller. But the bitwise or otherwise loses! What?!
Anyway, this is at a point where I'm comfortable merging it.