Hi All...
Im pretty far down a rabbithole with trying to make a set of macros that will do all my GPIO bit shifting and logical OR'ing to build up 32-bit variables in such a way that when I move I/O pins around on a schematic, it is much easier to update the code.
In short, Im trying to move away from this type of thing.. which is fast but a 'bit' of a nightmare to maintain. Thanks in advance!!
register uint16_t address;
register uint32_t GPIO6_data=0;
register uint32_t GPIO7_data=0;
register uint32_t GPIO8_data=0;
register uint32_t GPIO9_data=0;
GPIO6_data = GPIO6_DR;
GPIO7_data = GPIO7_DR;
GPIO8_data = GPIO8_DR;
GPIO9_data = GPIO9_DR;
address = ( (GPIO6_data&0x00020000) >> 17 ) | // A0 Teensy 4.0 PIN_18 GPIO6_DR[17]
( (GPIO6_data&0x00010000) >> 15 ) | // A1 Teensy 4.0 PIN_19 GPIO6_DR[16]
( (GPIO6_data&0x04000000) >> 24 ) | // A2 Teensy 4.0 PIN_20 GPIO6_DR[26]
( (GPIO7_data&0x00000800) >> 8 ) | // A3 Teensy 4.0 PIN_9 GPIO7_DR[11]
( (GPIO7_data&0x00020000) >> 13 ) | // A4 Teensy 4.0 PIN_7 GPIO7_DR[17]
( (GPIO9_data&0x00000100) >> 3 ) | // A5 Teensy 4.0 PIN_5 GPIO9_DR[8]
( (GPIO6_data&0x01000000) >> 18 ) | // A6 Teensy 4.0 PIN_22 GPIO6_DR[24]
( (GPIO9_data&0x00000040) << 1 ) | // A7 Teensy 4.0 PIN_4 GPIO9_DR[6]
( (GPIO6_data&0x02000000) >> 17 ) | // A8 Teensy 4.0 PIN_23 GPIO6_DR[25]
( (GPIO6_data&0x08000000) >> 18 ) | // A9 Teensy 4.0 PIN_21 GPIO6_DR[27]
( (GPIO7_data&0x00010000) >> 6 ) | // A10 Teensy 4.0 PIN_8 GPIO7_DR[16]
( (GPIO7_data&0x00000400) << 1 ) | // A11 Teensy 4.0 PIN_6 GPIO7_DR[10]
( (GPIO9_data&0x00000010) << 8 ) | // A12 Teensy 4.0 PIN_2 GPIO9_DR[4]
( (GPIO9_data&0x00000020) << 8 ) | // A13 Teensy 4.0 PIN_3 GPIO9_DR[5]
( (GPIO6_data&0x00000004) << 12 ) | // A14 Teensy 4.0 PIN_1 GPIO6_DR[2]
( (GPIO6_data&0x00000008) << 12 ) ; // A15 Teensy 4.0 PIN_0 GPIO6_DR[3]
... and more towards something like this.. note that the incrementing number in the second parameter to MAPR and MAPL is the bit position that I want the GPIO bit to be in this case for a 16-bit variable.
address = (MAPR(PIN_ADDR0,0)) |
(MAPR(PIN_ADDR1,1))|
(MAPR(PIN_ADDR2,2))|
(MAPR(PIN_ADDR3,3))|
(MAPR(PIN_ADDR4,4))|
(MAPR(PIN_ADDR5,5))|
(MAPL(PIN_ADDR6,6))|
(MAPL(PIN_ADDR7,7))|
(MAPR(PIN_ADDR8,8))|
(MAPR(PIN_ADDR9,9))|
(MAPR(PIN_ADDR10,10))|
(MAPR(PIN_ADDR11,11))|
(MAPL(PIN_ADDR12,12))|
(MAPR(PIN_ADDR13,13))|
(MAPR(PIN_ADDR14,14))|
(MAPL(PIN_ADDR15,15));
First caveat... I KNOW this is just making something overly complicated in the opposite direction. But if I can define these MACROS, then I can use this approach on all my projects and it will save time.
The reason I needed to have a MAPR and a MAPL is that sometimes the original GPIO bit location is to the LEFT of the target/wanted bit position and sometimes it is to the RIGHT. So I end up having to have two different #defines as I can't pass negative numbers to a bitwise shift operator.
Second caveat... I'm going to this extreme as well because Im trying to do the GPIO reads as fast as possible so I don't want any code execution, or am I being silly?
#define MAPR(pin,targetbit) ((REGISTER(pin)&(1<<BITSH(pin)) >> (BITSH(pin)-targetbit)))
#define MAPL(pin,targetbit) ((REGISTER(pin)&(1<<BITSH(pin)) << (targetbit-BITSH(pin))))
My question is how can I get away from having double MACROS based upon if I need to shift right or left?
Ideas I had that don't work
1. negative shifting - compiler error
2. over-shifting (like rotating) - shifts can't rotate
3. #if inside of #define - not allowed
Here are all the DEFINES that allow this to work.
#define PIN_ADDR0 9
#define PIN_ADDR1 8
#define PIN_ADDR2 7
#define PIN_ADDR3 6
#define PIN_ADDR4 5
#define PIN_ADDR5 4
#define PIN_ADDR6 3
#define PIN_ADDR7 2
#define PIN_ADDR8 22
#define PIN_ADDR9 28
#define PIN_ADDR10 26
#define PIN_ADDR11 27
#define PIN_ADDR12 1
#define PIN_ADDR13 23
#define PIN_ADDR14 17
#define PIN_ADDR15 0
//The macros below are based upon the output of the GPIO map for the Teensy 4.0
//PIN GPIOn-BITm | GPIOn-BITm PIN
//------------------|-------------------
//00 -> GPIO6-03 | GIPO6-02 -> 01
//01 -> GPIO6-02 | GIPO6-03 -> 00
//02 -> GPIO9-04 | GIPO6-12 -> 24
//03 -> GPIO9-05 | GIPO6-13 -> 25
//04 -> GPIO9-06 | GIPO6-16 -> 19
//05 -> GPIO9-08 | GIPO6-17 -> 18
//06 -> GPIO7-10 | GIPO6-18 -> 14
//07 -> GPIO7-17 | GIPO6-19 -> 15
//08 -> GPIO7-16 | GIPO6-22 -> 17
//09 -> GPIO7-11 | GIPO6-23 -> 16
//10 -> GPIO7-00 | GIPO6-24 -> 22
//11 -> GPIO7-02 | GIPO6-25 -> 23
//12 -> GPIO7-01 | GIPO6-26 -> 20
//13 -> GPIO7-03 | GIPO6-27 -> 21
//14 -> GPIO6-18 | GIPO6-30 -> 26
//15 -> GPIO6-19 | GIPO6-31 -> 27
//16 -> GPIO6-23 | GIPO7-00 -> 10
//17 -> GPIO6-22 | GIPO7-01 -> 12
//18 -> GPIO6-17 | GIPO7-02 -> 11
//19 -> GPIO6-16 | GIPO7-03 -> 13
//20 -> GPIO6-26 | GIPO7-10 -> 06
//21 -> GPIO6-27 | GIPO7-11 -> 09
//22 -> GPIO6-24 | GIPO7-12 -> 32
//23 -> GPIO6-25 | GIPO7-16 -> 08
//24 -> GPIO6-12 | GIPO7-17 -> 07
//25 -> GPIO6-13 | GIPO8-12 -> 37
//26 -> GPIO6-30 | GIPO8-13 -> 36
//27 -> GPIO6-31 | GIPO8-14 -> 35
//28 -> GPIO8-18 | GIPO8-15 -> 34
//29 -> GPIO9-31 | GIPO8-16 -> 39
//30 -> GPIO8-23 | GIPO8-17 -> 38
//31 -> GPIO8-22 | GIPO8-18 -> 28
//32 -> GPIO7-12 | GIPO8-22 -> 31
//33 -> GPIO9-07 | GIPO8-23 -> 30
//34 -> GPIO8-15 | GIPO9-04 -> 02
//35 -> GPIO8-14 | GIPO9-05 -> 03
//36 -> GPIO8-13 | GIPO9-06 -> 04
//37 -> GPIO8-12 | GIPO9-07 -> 33
//38 -> GPIO8-17 | GIPO9-08 -> 05
//39 -> GPIO8-16 | GIPO9-31 -> 29
#define _r0 GPIO6_data
#define _p0 3
#define _r1 GPIO6_data
#define _p1 2
#define _r2 GPIO9_data
#define _p2 4
#define _r3 GPIO9_data
#define _p3 5
#define _r4 GPIO9_data
#define _p4 6
#define _r5 GPIO9_data
#define _p5 8
#define _r6 GPIO7_data
#define _p6 10
#define _r7 GPIO7_data
#define _p7 17
#define _r8 GPIO7_data
#define _p8 16
#define _r9 GPIO7_data
#define _p9 11
#define _r10 GPIO7_data
#define _p10 0
#define _r11 GPIO7_data
#define _p11 2
#define _r12 GPIO7_data
#define _p12 1
#define _r13 GPIO7_data
#define _p13 3
#define _r14 GPIO6_data
#define _p14 18
#define _r15 GPIO6_data
#define _p15 19
#define _r16 GPIO6_data
#define _p16 23
#define _r17 GPIO6_data
#define _p17 22
#define _r18 GPIO6_data
#define _p18 17
#define _r19 GPIO6_data
#define _p19 16
#define _r20 GPIO6_data
#define _p20 26
#define _r21 GPIO6_data
#define _p21 27
#define _r22 GPIO6_data
#define _p22 24
#define _r23 GPIO6_data
#define _p23 25
#define _r24 GPIO6_data
#define _p24 12
#define _r25 GPIO6_data
#define _p25 13
#define _r26 GPIO6_data
#define _p26 30
#define _r27 GPIO6_data
#define _p27 31
#define _r28 GPIO8_data
#define _p28 18
#define _r29 GPIO9_data
#define _p29 31
#define _r30 GPIO8_data
#define _p30 23
#define _r31 GPIO8_data
#define _p31 22
#define _r32 GPIO7_data
#define _p32 12
#define _r33 GPIO9_data
#define _p33 7
#define _r34 GPIO8_data
#define _p34 15
#define _r35 GPIO8_data
#define _p35 14
#define _r36 GPIO8_data
#define _p36 13
#define _r37 GPIO8_data
#define _p37 12
#define _r38 GPIO8_data
#define _p38 17
#define _r39 GPIO8_data
#define _p39 16
#define REGISTER(pin) _r##pin
#define BITSH(pin) _p##pin
Im pretty far down a rabbithole with trying to make a set of macros that will do all my GPIO bit shifting and logical OR'ing to build up 32-bit variables in such a way that when I move I/O pins around on a schematic, it is much easier to update the code.
In short, Im trying to move away from this type of thing.. which is fast but a 'bit' of a nightmare to maintain. Thanks in advance!!
register uint16_t address;
register uint32_t GPIO6_data=0;
register uint32_t GPIO7_data=0;
register uint32_t GPIO8_data=0;
register uint32_t GPIO9_data=0;
GPIO6_data = GPIO6_DR;
GPIO7_data = GPIO7_DR;
GPIO8_data = GPIO8_DR;
GPIO9_data = GPIO9_DR;
address = ( (GPIO6_data&0x00020000) >> 17 ) | // A0 Teensy 4.0 PIN_18 GPIO6_DR[17]
( (GPIO6_data&0x00010000) >> 15 ) | // A1 Teensy 4.0 PIN_19 GPIO6_DR[16]
( (GPIO6_data&0x04000000) >> 24 ) | // A2 Teensy 4.0 PIN_20 GPIO6_DR[26]
( (GPIO7_data&0x00000800) >> 8 ) | // A3 Teensy 4.0 PIN_9 GPIO7_DR[11]
( (GPIO7_data&0x00020000) >> 13 ) | // A4 Teensy 4.0 PIN_7 GPIO7_DR[17]
( (GPIO9_data&0x00000100) >> 3 ) | // A5 Teensy 4.0 PIN_5 GPIO9_DR[8]
( (GPIO6_data&0x01000000) >> 18 ) | // A6 Teensy 4.0 PIN_22 GPIO6_DR[24]
( (GPIO9_data&0x00000040) << 1 ) | // A7 Teensy 4.0 PIN_4 GPIO9_DR[6]
( (GPIO6_data&0x02000000) >> 17 ) | // A8 Teensy 4.0 PIN_23 GPIO6_DR[25]
( (GPIO6_data&0x08000000) >> 18 ) | // A9 Teensy 4.0 PIN_21 GPIO6_DR[27]
( (GPIO7_data&0x00010000) >> 6 ) | // A10 Teensy 4.0 PIN_8 GPIO7_DR[16]
( (GPIO7_data&0x00000400) << 1 ) | // A11 Teensy 4.0 PIN_6 GPIO7_DR[10]
( (GPIO9_data&0x00000010) << 8 ) | // A12 Teensy 4.0 PIN_2 GPIO9_DR[4]
( (GPIO9_data&0x00000020) << 8 ) | // A13 Teensy 4.0 PIN_3 GPIO9_DR[5]
( (GPIO6_data&0x00000004) << 12 ) | // A14 Teensy 4.0 PIN_1 GPIO6_DR[2]
( (GPIO6_data&0x00000008) << 12 ) ; // A15 Teensy 4.0 PIN_0 GPIO6_DR[3]
... and more towards something like this.. note that the incrementing number in the second parameter to MAPR and MAPL is the bit position that I want the GPIO bit to be in this case for a 16-bit variable.
address = (MAPR(PIN_ADDR0,0)) |
(MAPR(PIN_ADDR1,1))|
(MAPR(PIN_ADDR2,2))|
(MAPR(PIN_ADDR3,3))|
(MAPR(PIN_ADDR4,4))|
(MAPR(PIN_ADDR5,5))|
(MAPL(PIN_ADDR6,6))|
(MAPL(PIN_ADDR7,7))|
(MAPR(PIN_ADDR8,8))|
(MAPR(PIN_ADDR9,9))|
(MAPR(PIN_ADDR10,10))|
(MAPR(PIN_ADDR11,11))|
(MAPL(PIN_ADDR12,12))|
(MAPR(PIN_ADDR13,13))|
(MAPR(PIN_ADDR14,14))|
(MAPL(PIN_ADDR15,15));
First caveat... I KNOW this is just making something overly complicated in the opposite direction. But if I can define these MACROS, then I can use this approach on all my projects and it will save time.
The reason I needed to have a MAPR and a MAPL is that sometimes the original GPIO bit location is to the LEFT of the target/wanted bit position and sometimes it is to the RIGHT. So I end up having to have two different #defines as I can't pass negative numbers to a bitwise shift operator.
Second caveat... I'm going to this extreme as well because Im trying to do the GPIO reads as fast as possible so I don't want any code execution, or am I being silly?
#define MAPR(pin,targetbit) ((REGISTER(pin)&(1<<BITSH(pin)) >> (BITSH(pin)-targetbit)))
#define MAPL(pin,targetbit) ((REGISTER(pin)&(1<<BITSH(pin)) << (targetbit-BITSH(pin))))
My question is how can I get away from having double MACROS based upon if I need to shift right or left?
Ideas I had that don't work
1. negative shifting - compiler error
2. over-shifting (like rotating) - shifts can't rotate
3. #if inside of #define - not allowed
Here are all the DEFINES that allow this to work.
#define PIN_ADDR0 9
#define PIN_ADDR1 8
#define PIN_ADDR2 7
#define PIN_ADDR3 6
#define PIN_ADDR4 5
#define PIN_ADDR5 4
#define PIN_ADDR6 3
#define PIN_ADDR7 2
#define PIN_ADDR8 22
#define PIN_ADDR9 28
#define PIN_ADDR10 26
#define PIN_ADDR11 27
#define PIN_ADDR12 1
#define PIN_ADDR13 23
#define PIN_ADDR14 17
#define PIN_ADDR15 0
//The macros below are based upon the output of the GPIO map for the Teensy 4.0
//PIN GPIOn-BITm | GPIOn-BITm PIN
//------------------|-------------------
//00 -> GPIO6-03 | GIPO6-02 -> 01
//01 -> GPIO6-02 | GIPO6-03 -> 00
//02 -> GPIO9-04 | GIPO6-12 -> 24
//03 -> GPIO9-05 | GIPO6-13 -> 25
//04 -> GPIO9-06 | GIPO6-16 -> 19
//05 -> GPIO9-08 | GIPO6-17 -> 18
//06 -> GPIO7-10 | GIPO6-18 -> 14
//07 -> GPIO7-17 | GIPO6-19 -> 15
//08 -> GPIO7-16 | GIPO6-22 -> 17
//09 -> GPIO7-11 | GIPO6-23 -> 16
//10 -> GPIO7-00 | GIPO6-24 -> 22
//11 -> GPIO7-02 | GIPO6-25 -> 23
//12 -> GPIO7-01 | GIPO6-26 -> 20
//13 -> GPIO7-03 | GIPO6-27 -> 21
//14 -> GPIO6-18 | GIPO6-30 -> 26
//15 -> GPIO6-19 | GIPO6-31 -> 27
//16 -> GPIO6-23 | GIPO7-00 -> 10
//17 -> GPIO6-22 | GIPO7-01 -> 12
//18 -> GPIO6-17 | GIPO7-02 -> 11
//19 -> GPIO6-16 | GIPO7-03 -> 13
//20 -> GPIO6-26 | GIPO7-10 -> 06
//21 -> GPIO6-27 | GIPO7-11 -> 09
//22 -> GPIO6-24 | GIPO7-12 -> 32
//23 -> GPIO6-25 | GIPO7-16 -> 08
//24 -> GPIO6-12 | GIPO7-17 -> 07
//25 -> GPIO6-13 | GIPO8-12 -> 37
//26 -> GPIO6-30 | GIPO8-13 -> 36
//27 -> GPIO6-31 | GIPO8-14 -> 35
//28 -> GPIO8-18 | GIPO8-15 -> 34
//29 -> GPIO9-31 | GIPO8-16 -> 39
//30 -> GPIO8-23 | GIPO8-17 -> 38
//31 -> GPIO8-22 | GIPO8-18 -> 28
//32 -> GPIO7-12 | GIPO8-22 -> 31
//33 -> GPIO9-07 | GIPO8-23 -> 30
//34 -> GPIO8-15 | GIPO9-04 -> 02
//35 -> GPIO8-14 | GIPO9-05 -> 03
//36 -> GPIO8-13 | GIPO9-06 -> 04
//37 -> GPIO8-12 | GIPO9-07 -> 33
//38 -> GPIO8-17 | GIPO9-08 -> 05
//39 -> GPIO8-16 | GIPO9-31 -> 29
#define _r0 GPIO6_data
#define _p0 3
#define _r1 GPIO6_data
#define _p1 2
#define _r2 GPIO9_data
#define _p2 4
#define _r3 GPIO9_data
#define _p3 5
#define _r4 GPIO9_data
#define _p4 6
#define _r5 GPIO9_data
#define _p5 8
#define _r6 GPIO7_data
#define _p6 10
#define _r7 GPIO7_data
#define _p7 17
#define _r8 GPIO7_data
#define _p8 16
#define _r9 GPIO7_data
#define _p9 11
#define _r10 GPIO7_data
#define _p10 0
#define _r11 GPIO7_data
#define _p11 2
#define _r12 GPIO7_data
#define _p12 1
#define _r13 GPIO7_data
#define _p13 3
#define _r14 GPIO6_data
#define _p14 18
#define _r15 GPIO6_data
#define _p15 19
#define _r16 GPIO6_data
#define _p16 23
#define _r17 GPIO6_data
#define _p17 22
#define _r18 GPIO6_data
#define _p18 17
#define _r19 GPIO6_data
#define _p19 16
#define _r20 GPIO6_data
#define _p20 26
#define _r21 GPIO6_data
#define _p21 27
#define _r22 GPIO6_data
#define _p22 24
#define _r23 GPIO6_data
#define _p23 25
#define _r24 GPIO6_data
#define _p24 12
#define _r25 GPIO6_data
#define _p25 13
#define _r26 GPIO6_data
#define _p26 30
#define _r27 GPIO6_data
#define _p27 31
#define _r28 GPIO8_data
#define _p28 18
#define _r29 GPIO9_data
#define _p29 31
#define _r30 GPIO8_data
#define _p30 23
#define _r31 GPIO8_data
#define _p31 22
#define _r32 GPIO7_data
#define _p32 12
#define _r33 GPIO9_data
#define _p33 7
#define _r34 GPIO8_data
#define _p34 15
#define _r35 GPIO8_data
#define _p35 14
#define _r36 GPIO8_data
#define _p36 13
#define _r37 GPIO8_data
#define _p37 12
#define _r38 GPIO8_data
#define _p38 17
#define _r39 GPIO8_data
#define _p39 16
#define REGISTER(pin) _r##pin
#define BITSH(pin) _p##pin