Author Topic: [gcc C] concatenating text to make up code  (Read 19930 times)

0 Members and 1 Guest are viewing this topic.

Offline ataradov

  • Super Contributor
  • ***
  • Posts: 11248
  • Country: us
    • Personal site
Re: [gcc C] concatenating text to make up code
« Reply #150 on: October 13, 2018, 09:52:42 pm »
How? At the moment I cannot make much sense of that file as it appears that to reference anything I have to pull together different sections that are likely to be many lines apart.
I don't understand what is your problem with that file. You don't need to look at it most of the time once you get used to naming conventions. You can read the datasheet and write code and expect that things you need will be defined.

ARM files are much better, of course, since this carries some legacy AVR compatibility, so it could not be too far off the old tradition. But this is still plenty usable.
Alex
 

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 17814
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: [gcc C] concatenating text to make up code
« Reply #151 on: October 13, 2018, 09:57:57 pm »
If i want to write to porta.pin1 sure but if I want to put "a" and "1" in as arguments in a function then what? this puts me back to writing 48 lines all the same but for the ports and pins
 

Offline ataradov

  • Super Contributor
  • ***
  • Posts: 11248
  • Country: us
    • Personal site
Re: [gcc C] concatenating text to make up code
« Reply #152 on: October 13, 2018, 10:04:45 pm »
If your arguments are constant, then do it through a compiler macro that unrolls into the standard defines. That's easy:

Code: [Select]
#define PORT_SET(port, pin) PORT##port->OUTSET = (1 << pin)
Use
Code: [Select]
PORT_SET(A, 5);

If you want parameters to be taken from the variables (a really strange and rare requirement in real life scenarios), then the code you write is fine. Just don't reuse the same name.

This problem really only exists for ports, and even then it is not as big of a problem as you make it out to be.

One big thing this file is missing is direct (non-dereferenced) versions of defines like this:
Code: [Select]
#define PORTA (*(PORT_t *)0x0400)      /* I/O Ports */
...
#define AC0 (*(AC_t *)0x0680)          /* Analog Comparator */
...
And may be that's the only thing worth defining in addition to the stock file.
« Last Edit: October 13, 2018, 10:13:53 pm by ataradov »
Alex
 

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 17814
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: [gcc C] concatenating text to make up code
« Reply #153 on: October 13, 2018, 10:10:49 pm »
What like:

#define PORTA                (*(PORT_t *) 0x0400) /* I/O Ports */
#define PORTB                (*(PORT_t *) 0x0420) /* I/O Ports */
#define PORTC                (*(PORT_t *) 0x0440) /* I/O Ports */
#define PORTD                (*(PORT_t *) 0x0460) /* I/O Ports */
#define PORTE                (*(PORT_t *) 0x0480) /* I/O Ports */
#define PORTF                (*(PORT_t *) 0x04A0) /* I/O Ports */
 

Offline ataradov

  • Super Contributor
  • ***
  • Posts: 11248
  • Country: us
    • Personal site
Re: [gcc C] concatenating text to make up code
« Reply #154 on: October 13, 2018, 10:13:42 pm »
What like:
What like? Those are dereferenced versions. What you want is this:

Code: [Select]
#define PORTA (PORT_t *)0x0400

This way you can write functions like this:

Code: [Select]
void out_set(PORT_t *port, int pin)
{
  port->OUTSET = (1<<pin);
}
And use them like this:
Code: [Select]
out_set(PORTA, 3);
Alex
 

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 17814
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: [gcc C] concatenating text to make up code
« Reply #155 on: October 13, 2018, 10:13:52 pm »
I should be able to avoid same names, I am trying to avoid writing every piece of code over by giving arguments to a function rather than having to write the same code for every instance of the same thing.

All the manufacturers header file seems to do in do roundabout defines of every address.
 

Offline NorthGuy

  • Super Contributor
  • ***
  • Posts: 3146
  • Country: ca
Re: [gcc C] concatenating text to make up code
« Reply #156 on: October 13, 2018, 10:15:54 pm »
If i want to write to porta.pin1 sure but if I want to put "a" and "1" in as arguments in a function then what? this puts me back to writing 48 lines all the same but for the ports and pins

If you know what are you going to pass to the function, then doing my_function(a,1) or MY_MACRO(a,1) it's about the same as assigning to PORTA, except you're doing a lot of extra work defining your own entities.

If you do not know what are you going to pass (say you save the pin number in a variable which may change at run-time, and then you pass the variable to the function), then what has been discussed in this thread is mostly not applicable. In this case, the compiler will not be able to reduce your functions to almost nothing, but will literally execute the code your wrote.

 

Offline ataradov

  • Super Contributor
  • ***
  • Posts: 11248
  • Country: us
    • Personal site
Re: [gcc C] concatenating text to make up code
« Reply #157 on: October 13, 2018, 10:17:50 pm »
All the manufacturers header file seems to do in do roundabout defines of every address.
The other way around. What you are doing is a roundabout way to not use manufacturer files.
Alex
 

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 17814
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: [gcc C] concatenating text to make up code
« Reply #158 on: October 13, 2018, 10:18:19 pm »
This is out of their header:

Code: [Select]
==========================================================================
IO Module Instances. Mapped to memory.
==========================================================================
*/

#define VPORTA              (*(VPORT_t *) 0x0000) /* Virtual Ports */
#define VPORTB              (*(VPORT_t *) 0x0004) /* Virtual Ports */
#define VPORTC              (*(VPORT_t *) 0x0008) /* Virtual Ports */
#define VPORTD              (*(VPORT_t *) 0x000C) /* Virtual Ports */
#define VPORTE              (*(VPORT_t *) 0x0010) /* Virtual Ports */
#define VPORTF              (*(VPORT_t *) 0x0014) /* Virtual Ports */
#define RSTCTRL           (*(RSTCTRL_t *) 0x0040) /* Reset controller */
#define SLPCTRL           (*(SLPCTRL_t *) 0x0050) /* Sleep Controller */
#define CLKCTRL           (*(CLKCTRL_t *) 0x0060) /* Clock controller */
#define BOD                   (*(BOD_t *) 0x0080) /* Bod interface */
#define VREF                 (*(VREF_t *) 0x00A0) /* Voltage reference */
#define NVMBIST           (*(NVMBIST_t *) 0x00C0) /* BIST in the NVMCTRL module */
#define WDT                   (*(WDT_t *) 0x0100) /* Watch-Dog Timer */
#define CPUINT             (*(CPUINT_t *) 0x0110) /* Interrupt Controller */
#define CRCSCAN           (*(CRCSCAN_t *) 0x0120) /* CRCSCAN */
#define RTC                   (*(RTC_t *) 0x0140) /* Real-Time Counter */
#define EVSYS               (*(EVSYS_t *) 0x0180) /* Event System */
#define CCL                   (*(CCL_t *) 0x01C0) /* Configurable Custom Logic */
#define PORTA                (*(PORT_t *) 0x0400) /* I/O Ports */
#define PORTB                (*(PORT_t *) 0x0420) /* I/O Ports */
#define PORTC                (*(PORT_t *) 0x0440) /* I/O Ports */
#define PORTD                (*(PORT_t *) 0x0460) /* I/O Ports */
#define PORTE                (*(PORT_t *) 0x0480) /* I/O Ports */
#define PORTF                (*(PORT_t *) 0x04A0) /* I/O Ports */
#define PORTMUX           (*(PORTMUX_t *) 0x05E0) /* Port Multiplexer */
#define ADC0                  (*(ADC_t *) 0x0600) /* Analog to Digital Converter */
#define AC0                    (*(AC_t *) 0x0680) /* Analog Comparator */
#define USART0              (*(USART_t *) 0x0800) /* Universal Synchronous and Asynchronous Receiver and Transmitter */
#define USART1              (*(USART_t *) 0x0820) /* Universal Synchronous and Asynchronous Receiver and Transmitter */
#define USART2              (*(USART_t *) 0x0840) /* Universal Synchronous and Asynchronous Receiver and Transmitter */
#define USART3              (*(USART_t *) 0x0860) /* Universal Synchronous and Asynchronous Receiver and Transmitter */
#define TWI0                  (*(TWI_t *) 0x08A0) /* Two-Wire Interface */
#define SPI0                  (*(SPI_t *) 0x08C0) /* Serial Peripheral Interface */
#define TCA0                  (*(TCA_t *) 0x0A00) /* 16-bit Timer/Counter Type A */
#define TCB0                  (*(TCB_t *) 0x0A80) /* 16-bit Timer Type B */
#define TCB1                  (*(TCB_t *) 0x0A90) /* 16-bit Timer Type B */
#define TCB2                  (*(TCB_t *) 0x0AA0) /* 16-bit Timer Type B */
#define TCB3                  (*(TCB_t *) 0x0AB0) /* 16-bit Timer Type B */
#define SYSCFG             (*(SYSCFG_t *) 0x0F00) /* System Configuration Registers */
#define NVMCTRL           (*(NVMCTRL_t *) 0x1000) /* Non-volatile Memory Controller */
#define SIGROW             (*(SIGROW_t *) 0x1100) /* Signature row */
#define FUSE                 (*(FUSE_t *) 0x1280) /* Fuses */
#define LOCKBIT           (*(LOCKBIT_t *) 0x128A) /* Lockbit */
#define USERROW           (*(USERROW_t *) 0x1300) /* User Row */

#endif /* !defined (__ASSEMBLER__) */

but they never set a gap, all i have done is rewritten that for the first instance of any periphery category and then defined the offset between instances.
 

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 17814
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: [gcc C] concatenating text to make up code
« Reply #159 on: October 13, 2018, 10:20:38 pm »
All the manufacturers header file seems to do in do roundabout defines of every address.
The other way around. What you are doing is a roundabout way to not use manufacturer files.

I'd love to but i don't know where to start, the header file is for both assembler and C and it makes little sense. They did not produce this file to make anything easy for anyone as it looks like their idea was that we would use the code generator.
 

Offline ataradov

  • Super Contributor
  • ***
  • Posts: 11248
  • Country: us
    • Personal site
Re: [gcc C] concatenating text to make up code
« Reply #160 on: October 13, 2018, 10:22:01 pm »
This is out of their header:
I know. Do you see the difference between
Code: [Select]
#define PORTA (PORT_t *)0x0400
and
Code: [Select]
#define PORTA                (*(PORT_t *) 0x0400)
?

All you really need is the former. And that's what ARM files have.
If you define that, for example like this:

Code: [Select]
#define MY_PORTA (PORT_t *)0x0400

Then you will be able to create universal functions like this:

Code: [Select]
void out_set(PORT_t *port, int pin)
{
  port->OUTSET = (1<<pin);
}

What else do you need?
Alex
 

Offline ataradov

  • Super Contributor
  • ***
  • Posts: 11248
  • Country: us
    • Personal site
Re: [gcc C] concatenating text to make up code
« Reply #161 on: October 13, 2018, 10:24:28 pm »
I'd love to but i don't know where to start, the header file is for both assembler and C and it makes little sense. They did not produce this file to make anything easy for anyone as it looks like their idea was that we would use the code generator.
If you work with assembler, then look at the assembler parts, if you work with C, then look at C parts.

This file is almost perfect for everything you want to do in real life. Don't focus on writing universal libraries, it is a waste of time. Work on real projects and you will see that in reality you have all you need in that file.

ARM header files are perfect.

Work on learning how to use them even if you don't get it now. Avoiding them is much worse.
« Last Edit: October 13, 2018, 10:27:47 pm by ataradov »
Alex
 

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 17814
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: [gcc C] concatenating text to make up code
« Reply #162 on: October 13, 2018, 10:27:05 pm »
Well I'm off to bed, I'll do more headbanging tomorrow.
 

Offline cv007

  • Frequent Contributor
  • **
  • Posts: 825
Re: [gcc C] concatenating text to make up code
« Reply #163 on: October 13, 2018, 10:45:48 pm »
Code: [Select]
//test.c
#define _AVR_IO_H_ //I need to prevent error as I'm not using io.h
#include "sfr_defs.h"
#include "iom4809.h"
#include <stdint.h>

#define set_output(pt,pn)  pt.DIR |= (1<<pn)
#define set_voutput(pt,pn) _SFR_IO8(&V##pt.DIR) |= (1<<pn)

void main()
{
    set_output(PORTA, 2);
    set_voutput(PORTB, 3);
    for(;;);
}
/*
Disassembly of section .text:

00000000 <main>:
   0:   80 91 00 04     lds     r24, 0x0400     ; 0x800400 <_edata+0x3a0>
   4:   84 60           ori     r24, 0x04       ; 4
   6:   80 93 00 04     sts     0x0400, r24     ; 0x800400 <_edata+0x3a0>

   a:   23 9a           sbi     0x04, 3 ; 4

   c:   ff cf           rjmp    .-2             ; 0xc <__zero_reg__+0xb>
*/
Either PORT or VPORT can be used, but for some reason they don't seem to take advantage of the VPORT feature (all addresses in the header are mem addresses). I wrapped up the vport address into an io macro to make it work like its supposed to (using sbi).
 

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 17814
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: [gcc C] concatenating text to make up code
« Reply #164 on: October 14, 2018, 08:02:07 am »
Right so here is my quandary:

Code: [Select]
/* I/O Ports */
typedef struct PORT_struct
{
    register8_t DIR;  /* Data Direction */
    register8_t DIRSET;  /* Data Direction Set */
    register8_t DIRCLR;  /* Data Direction Clear */
    register8_t DIRTGL;  /* Data Direction Toggle */
    register8_t OUT;  /* Output Value */
    register8_t OUTSET;  /* Output Value Set */
    register8_t OUTCLR;  /* Output Value Clear */
    register8_t OUTTGL;  /* Output Value Toggle */
    register8_t IN;  /* Input Value */
    register8_t INTFLAGS;  /* Interrupt Flags */
    register8_t PORTCTRL;  /* Port Control */
    register8_t reserved_0x0B;
    register8_t reserved_0x0C;
    register8_t reserved_0x0D;
    register8_t reserved_0x0E;
    register8_t reserved_0x0F;
    register8_t PIN0CTRL;  /* Pin 0 Control */
    register8_t PIN1CTRL;  /* Pin 1 Control */
    register8_t PIN2CTRL;  /* Pin 2 Control */
    register8_t PIN3CTRL;  /* Pin 3 Control */
    register8_t PIN4CTRL;  /* Pin 4 Control */
    register8_t PIN5CTRL;  /* Pin 5 Control */
    register8_t PIN6CTRL;  /* Pin 6 Control */
    register8_t PIN7CTRL;  /* Pin 7 Control */
    register8_t reserved_0x18;
    register8_t reserved_0x19;
    register8_t reserved_0x1A;
    register8_t reserved_0x1B;
    register8_t reserved_0x1C;
    register8_t reserved_0x1D;
    register8_t reserved_0x1E;
    register8_t reserved_0x1F;
} PORT_t;

So this makes sense sort of, they create a variable type that is a structure containing all of the generic port registers and create the variable PORT_t

The next appearance of PORT_t is here:

Code: [Select]
==========================================================================
IO Module Instances. Mapped to memory.
==========================================================================
*/

#define VPORTA              (*(VPORT_t *) 0x0000) /* Virtual Ports */
#define VPORTB              (*(VPORT_t *) 0x0004) /* Virtual Ports */
#define VPORTC              (*(VPORT_t *) 0x0008) /* Virtual Ports */
#define VPORTD              (*(VPORT_t *) 0x000C) /* Virtual Ports */
#define VPORTE              (*(VPORT_t *) 0x0010) /* Virtual Ports */
#define VPORTF              (*(VPORT_t *) 0x0014) /* Virtual Ports */
#define RSTCTRL           (*(RSTCTRL_t *) 0x0040) /* Reset controller */
#define SLPCTRL           (*(SLPCTRL_t *) 0x0050) /* Sleep Controller */
#define CLKCTRL           (*(CLKCTRL_t *) 0x0060) /* Clock controller */
#define BOD                   (*(BOD_t *) 0x0080) /* Bod interface */
#define VREF                 (*(VREF_t *) 0x00A0) /* Voltage reference */
#define NVMBIST           (*(NVMBIST_t *) 0x00C0) /* BIST in the NVMCTRL module */
#define WDT                   (*(WDT_t *) 0x0100) /* Watch-Dog Timer */
#define CPUINT             (*(CPUINT_t *) 0x0110) /* Interrupt Controller */
#define CRCSCAN           (*(CRCSCAN_t *) 0x0120) /* CRCSCAN */
#define RTC                   (*(RTC_t *) 0x0140) /* Real-Time Counter */
#define EVSYS               (*(EVSYS_t *) 0x0180) /* Event System */
#define CCL                   (*(CCL_t *) 0x01C0) /* Configurable Custom Logic */
#define PORTA                (*(PORT_t *) 0x0400) /* I/O Ports */
#define PORTB                (*(PORT_t *) 0x0420) /* I/O Ports */
#define PORTC                (*(PORT_t *) 0x0440) /* I/O Ports */
#define PORTD                (*(PORT_t *) 0x0460) /* I/O Ports */
#define PORTE                (*(PORT_t *) 0x0480) /* I/O Ports */
#define PORTF                (*(PORT_t *) 0x04A0) /* I/O Ports */
#define PORTMUX           (*(PORTMUX_t *) 0x05E0) /* Port Multiplexer */
#define ADC0                  (*(ADC_t *) 0x0600) /* Analog to Digital Converter */
#define AC0                    (*(AC_t *) 0x0680) /* Analog Comparator */
#define USART0              (*(USART_t *) 0x0800) /* Universal Synchronous and Asynchronous Receiver and Transmitter */
#define USART1              (*(USART_t *) 0x0820) /* Universal Synchronous and Asynchronous Receiver and Transmitter */
#define USART2              (*(USART_t *) 0x0840) /* Universal Synchronous and Asynchronous Receiver and Transmitter */
#define USART3              (*(USART_t *) 0x0860) /* Universal Synchronous and Asynchronous Receiver and Transmitter */
#define TWI0                  (*(TWI_t *) 0x08A0) /* Two-Wire Interface */
#define SPI0                  (*(SPI_t *) 0x08C0) /* Serial Peripheral Interface */
#define TCA0                  (*(TCA_t *) 0x0A00) /* 16-bit Timer/Counter Type A */
#define TCB0                  (*(TCB_t *) 0x0A80) /* 16-bit Timer Type B */
#define TCB1                  (*(TCB_t *) 0x0A90) /* 16-bit Timer Type B */
#define TCB2                  (*(TCB_t *) 0x0AA0) /* 16-bit Timer Type B */
#define TCB3                  (*(TCB_t *) 0x0AB0) /* 16-bit Timer Type B */
#define SYSCFG             (*(SYSCFG_t *) 0x0F00) /* System Configuration Registers */
#define NVMCTRL           (*(NVMCTRL_t *) 0x1000) /* Non-volatile Memory Controller */
#define SIGROW             (*(SIGROW_t *) 0x1100) /* Signature row */
#define FUSE                 (*(FUSE_t *) 0x1280) /* Fuses */
#define LOCKBIT           (*(LOCKBIT_t *) 0x128A) /* Lockbit */
#define USERROW           (*(USERROW_t *) 0x1300) /* User Row */

So I do not understand how it understands PORTA.DIR, when was PORTA declared as a port struct type variable ?

can I "build my variables as you have appeared to do with "something.something_else" being two variables with a "." between them read by the compiler and understood?

 

Offline IanB

  • Super Contributor
  • ***
  • Posts: 11882
  • Country: us
Re: [gcc C] concatenating text to make up code
« Reply #165 on: October 14, 2018, 08:39:01 am »
So I do not understand how it understands PORTA.DIR, when was PORTA declared as a port struct type variable ?

From here:

Code: [Select]
#define PORTA                (*(PORT_t *) 0x0400) /* I/O Ports */

0x0400 is a raw memory address.

(PORT_t*)0x0400 is a pointer to a PORT_t structure (casting the raw memory address to a pointer of the right type).

*(PORT_t*)0x0400 is an actual PORT_t structure (dereferencing the pointer).

Therefore PORTA is an instance of a PORT_t type.
« Last Edit: October 14, 2018, 08:41:21 am by IanB »
 

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 17814
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: [gcc C] concatenating text to make up code
« Reply #166 on: October 14, 2018, 08:48:34 am »
OK that makes sense, so they are using the struct to automatically do what i do when i calculate the register offset from the start of the port because they use a structure that is declared to start at the address pointed to and goes up from there in order. This is why they have included all of the unused register addresses to make sure the numbers stay in sync.

So how flexible can I be with this? can I have the right text appear before the dot and the right text after and it correctly interprets things? I gather this does mean going to the dark side and using defines again for functions as I will be doing text replacements.

i don't need assignments to change at run time so the defines make sense as it will be clearer for the compiler to optimise.
 

Offline cv007

  • Frequent Contributor
  • **
  • Posts: 825
Re: [gcc C] concatenating text to make up code
« Reply #167 on: October 14, 2018, 11:08:08 am »
we have been here before-
https://www.eevblog.com/forum/microcontrollers/(atmega-0)-tcat-(aka-union-tca-union)-has-no-member-named-ctrl/msg1771667/#msg1771667

I think we are going in circles.

#define set_output(pt,pn)  pt.DIR |= (1<<pn)
set_output(PORTA, 2);

the pre-processor treats macro arguments as plain text at the first level (which is why we can use the already defined 'PORTA' as an argument, since its not 'expanded' yet)
so PORTA and 2 become pt and pn- as-is
now substitution takes place and you end up with PORTA.DIR = (1<<2), which then replaces 'set_output(PORTA, 2)' in your code source
(you can figure out what PORTA.DIR expands to)
so the compiler only sees '(*(volatile uint8_t *)(0x0400)) |= (1<<2);'
(also notice string concatenation is not required here with the struct . access)

#define set_voutput(pt,pn) _SFR_IO8(&V##pt.DIR) |= (1<<pn)
set_voutput(PORTB, 3);

the pre-processor treats macro arguments as plain text at the first level, so PORTB and 3 become pt and pn- as-is
now substitution takes place and you end up with _SFR_IO8(&VPORTA.DIR) |= (1<<3), but still not done (notice that V##pt becomes VPORTA)
now the pre-processor has to look for _SFR_IO8, and if exists passes '&VPORTA.DIR' to it (or maybe 0x400 as it now expanded)
I'm not going to go through the rest, because its another ~4 levels of macros in sfr_defs.h
but you end up with- the compiler only sees (*(volatile uint8_t *)((&(*(volatile uint8_t *)(0x0004))) + 0x20)) |= (1<<3);


you will have to learn about string concatenation in macros- which is not that easy to learn, and you end up in trial/error method to figure it out


here is another method, which uses the old style defines instead of struct types-

#define set_output(pt,pn)  pt##_DIR |= (1<<pn)
#define set_voutput(pt,pn) _SFR_IO8(&V##pt##_DIR) |= (1<<pn)

same result, pick your poison


 

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 17814
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: [gcc C] concatenating text to make up code
« Reply #168 on: October 14, 2018, 11:28:36 am »
Yes we have discussed concatenation in the past. But what i was asking for sure clarity on is that the struct type variables can be named by adding together two pieces of text rather than the actual concatenation operation. This does seem to be a better method as it means that i can do what i require without having to rewrite the headers and with other AVR chips having the same style of header the code will be portable. I think it will also be easier for the compiler to optimise the code which i am sure it would have done a good job of anyway.

Oh and sorry macro haters but macro's 1, inline functions 0,
 

Offline cv007

  • Frequent Contributor
  • **
  • Posts: 825
Re: [gcc C] concatenating text to make up code
« Reply #169 on: October 14, 2018, 12:44:09 pm »
Quote
can be named by adding together two pieces of text rather than the actual concatenation operation
Then why do you think everyone uses string concatenation if there were better alternatives? There is no better magic available.

Quote
Oh and sorry macro haters but macro's 1, inline functions 0,
No, it couldn't possibly be done without macros-

Code: [Select]
//test.c
#define _AVR_IO_H_ //I need to prevent error as I'm not using io.h
#include "iom4809.h"
#include <stdint.h>
#include <stdbool.h>

typedef enum {
    A0=0x00, A1, A2, A3, A4, A5, A6, A7,
    B0=0x20, B1, B2, B3, B4, B5, B6, B7,
    C0=0x40, C1, C2, C3, C4, C5, C6, C7,
    D0=0x60, D1, D2, D3, D4, D5, D6, D7,
    E0=0x80, E1, E2, E3, E4, E5, E6, E7,
    F0=0xA0, F1, F2, F3, F4, F5, F6, F7,
    //all my pin info here
    SW1=A2, LED1=B3
} PIN_t;

typedef enum { DIR_IN, DIR_OUT } DIR_t;

//I am adding 0x20 'manually' since I don't want to do the _SFR_IO8 incantation
//the result is the compiler will use the cbi/sbi/in/out instructions for these vports

static inline void pin_dir(PIN_t p, DIR_t d){
    if(d) ((volatile uint8_t*)&VPORTA.DIR+0x20)[p>>3] |=    1<<(p&7);
    else  ((volatile uint8_t*)&VPORTA.DIR+0x20)[p>>3] &=  ~(1<<(p&7));
}
static inline void pin_set(PIN_t p, bool tf){
    if(tf) ((volatile uint8_t*)&VPORTA.OUT+0x20)[p>>3] |=    1<<(p&7);
    else   ((volatile uint8_t*)&VPORTA.OUT+0x20)[p>>3] &=  ~(1<<(p&7));
}
static inline bool pin_get(PIN_t p)
{
    return ((volatile uint8_t*)&VPORTA.IN+0x20)[p>>3] & (1<<(p&7));
}

void main()
{
    pin_dir(LED1, DIR_OUT);
    pin_dir(SW1,  DIR_IN );

    for(;;){
        pin_set( LED1, pin_get(SW1) );
    }
}
/*
./avr-gcc -C -Os test.c && ./avr-objdump -d a.out

00000000 <main>:
   0:   23 9a           sbi     0x04, 3 ; 4
   2:   02 98           cbi     0x00, 2 ; 0
   4:   12 9b           sbis    0x02, 2 ; 2
   6:   02 c0           rjmp    .+4             ; 0xc <__zero_reg__+0xb>
   8:   2b 9a           sbi     0x05, 3 ; 5
   a:   fc cf           rjmp    .-8             ; 0x4 <__zero_reg__+0x3>
   c:   2b 98           cbi     0x05, 3 ; 5
   e:   fa cf           rjmp    .-12            ; 0x4 <__zero_reg__+0x3>
*/

exact same result using their headers, so I'm not sure what you are talking about


edit-
you can also use _SFR_IO8, and change the enums to simply increment from 0-
Code: [Select]
typedef enum {
    A0, A1, A2, A3, A4, A5, A6, A7,
    B0, B1, B2, B3, B4, B5, B6, B7,
    C0, C1, C2, C3, C4, C5, C6, C7,
    D0, D1, D2, D3, D4, D5, D6, D7,
    E0, E1, E2, E3, E4, E5, E6, E7,
    F0, F1, F2, F3, F4, F5, F6, F7,
    //all my pin info here
    SW1=A2, LED1=B3
} PIN_t;

typedef enum { DIR_IN, DIR_OUT } DIR_t;

static inline void pin_dir(PIN_t p, DIR_t d){
    if(d)  (&_SFR_IO8(&VPORTA.DIR))[p>>3<<2] |=   1<<(p&7);
    else   (&_SFR_IO8(&VPORTA.DIR))[p>>3<<2] &= ~(1<<(p&7));
}
static inline void pin_set(PIN_t p, bool tf){
    if(tf) (&_SFR_IO8(&VPORTA.OUT))[p>>3<<2] |=   1<<(p&7);
    else   (&_SFR_IO8(&VPORTA.OUT))[p>>3<<2] &= ~(1<<(p&7));
}
static inline bool pin_get(PIN_t p)
{
    return (&_SFR_IO8(&VPORTA.IN))[p>>3<<2] & (1<<(p&7));
}

There are many ways to say the same thing.
« Last Edit: October 14, 2018, 04:11:12 pm by cv007 »
 

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 17814
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: [gcc C] concatenating text to make up code
« Reply #170 on: October 14, 2018, 01:13:38 pm »
Now I understand their headers better I have nothing to talk about :)
 

Offline Siwastaja

  • Super Contributor
  • ***
  • Posts: 8172
  • Country: fi
Re: [gcc C] concatenating text to make up code
« Reply #171 on: October 15, 2018, 09:17:59 am »
Don't focus on writing universal libraries, it is a waste of time. Work on real projects and you will see that in reality you have all you need in that file.

This.

As a beginner, what you need most is exposure to real-world projects; that's the only way you learn how everything works, and especially, how would you like everything to work. As you gain experience, you find out the actual pain points, and you also find out ways to make them better without too much head banging. It may be something as simple as twenty lines of helper macros around the existing manufacturer #defines.
 

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 17814
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: [gcc C] concatenating text to make up code
« Reply #172 on: October 15, 2018, 11:07:01 am »
Indeed, I have given up and will start work on my first project with this chip. i am writing myself a word document instead to make notes of procedures and code snippets.
 

Offline Mattjd

  • Regular Contributor
  • *
  • Posts: 230
  • Country: us
Re: [gcc C] concatenating text to make up code
« Reply #173 on: October 17, 2018, 11:41:40 pm »
Im very late to the party, but OP, this is what you want I suppose?

Code: [Select]
#ifndef _GPIOMacros_
#define _GPIOMacros_
#include <msp430.h>
//Digital I/O registers
// P1IV - Port 1 Interrupt Vector
// P1IES - Port 1 Interrupt Edge Select
#define PORT1_INTERRUPT_PIN_ON_POS_EDGE(pin) P1IES &= ~BIT ## pin
#define PORT1_INTERRUPT_PIN_ON_NEG_EDGE(pin) P1IES |= BIT ## pin
// P1IE - Port 1 Interrupt Enable
#define ENABLE_PORT1_INTERRUPTS_PIN(pin) P1IE |= BIT ## pin
#define DISABLE_PORT1_INTERRUPTS_PIN(pin) P1IE &= ~BIT ## pin
// P1IFG - Port 1 Interrupt Flag
    #define CLEAR_PORT1_FLAG_PIN(pin) P1IFG &= ~BIT ## pin
#define SET_PORT1_FLAG_PIN(pin) P1IFG |= BIT ## pin
// P2IES - Port 2 Interrupt Edge Select
#define PORT2_INTERRUPT_PIN_ON_POS_EDGE(pin) P2IES &= ~BIT ## pin
#define PORT2_INTERRUPT_PIN_ON_NEG_EDGE(pin) P2IES |= BIT ## pin
// P2IE - Port 2 Interrupt Enable
#define ENABLE_PORT2_INTERRUPTS_PIN(pin) P2IE |= BIT ## pin
#define DISABLE_PORT2_INTERRUPTS_PIN(pin) P2IE &= ~BIT ## pin
// P2IFG - Port 2 Interrupt Flag
    #define CLEAR_PORT2_FLAG_PIN(pin) P2IFG &= ~BIT ## pin
#define SET_PORT2_FLAG_PIN(pin) P2IFG |= BIT ## pin
// PxIN - Port x Input
#define READ_GPIO_INPUT(port,pin) P ## port ## IN & BIT ## pin // Note to Self: Assume P1IN = 8'b10000000 then P1IN & BIT7 = 128
// PxOUT - Port x Output
#define GPIO_OUT(port) P ## port ## OUT
// PxDIR - Port x Direction
#define GPIO_DIR(port) P ## port ## DIR
// PxREN - Port x Resistor
#define GPIO_REN(port) P ## port ## REN
// PxDS - Port x Drive Strength
#define GPIO_DS(port) P ## port ## DS
// PxSEL - Port x Peripheral Selection
#define GPIO_SEL(port) P ## port ## SEL
// Pin Selections - (Input OR Output) & (Peripheral OR NO_Peripheral)
#define SET_GPIO_AS_OUTPUT(port,pin) GPIO_SEL(port) &= ~BIT ## pin; \
GPIO_DIR(port) |= BIT ## pin; \
GPIO_OUT(port) &= ~BIT ## pin;
#define SET_GPIO_AS_INPUT(port,pin) GPIO_SEL(port) &= ~BIT ## pin; \
GPIO_DIR(port) &= ~BIT ## pin;
#define USE_GPIO_PERIPHERAL_AS_OUTPUT(port,pin) GPIO_SEL(port) |= BIT ## pin; \
GPIO_DIR(port) |= BIT ## pin;
#define USE_GPIO_PERIPHERAL_AS_INPUT(port,pin) GPIO_SEL(port) |= BIT ## pin; \
GPIO_DIR(port) &= ~BIT ## pin;
#define ENABLE_PIN_RESISTOR(port,pin) GPIO_REN(port) |= BIT ## pin;
#define DISABLE_PIN_RESISTOR(port,pin) GPIO_REN(port) &= ~BIT ## pin;
#define SET_GPIO_OUTPUT_HIGH(port,pin) GPIO_OUT(port) |= BIT ## pin;
#define SET_GPIO_OUTPUT_LOW(port,pin) GPIO_OUT(port) &= ~BIT ## pin;
#define TOGGLE_GPIO_OUTPUT(port,pin) GPIO_OUT(port) ^= BIT ## pin;
// Resistor Selection - Pullup OR Pulldown
// Note to Self: Pull Up means Active Low (MCU receives a 1 until button is pressed), Pull Down Means Active High (MCU receives a 0 untill button is pressed)
#define SET_GPIO_RESISTOR_AS_PULLUP(port,pin) SET_GPIO_AS_INPUT(port,pin); \
  ENABLE_PIN_RESISTOR(port,pin); \
  SET_GPIO_OUTPUT_HIGH(port,pin);
#define SET_GPIO_RESISTOR_AS_PULLDOWN(port,pin) SET_GPIO_AS_INPUT(port,pin); \
ENABLE_PIN_RESISTOR(port,pin); \
SET_GPIO_OUTPUT_LOW(port,pin);
#endif // _GPIOMacros_


which I then use to build this?

Code: [Select]
#ifndef _DevelopmentBoardMacros_
#define _DevelopmentBoardMacros_
#include <msp430.h>
#include "GPIOMacros.h"
// Development Board Specific Macros
// BUTTONS - Switch1 is pin 2.1 and Switch2 is pin 1.1
// Note to Self: Button Interrupts appear to not work when using Active High (pull down configuration), use only Active Low (pull up)
#define CONFIGURE_INTERRUPT_SWITCH1_ON_PRESS SET_GPIO_RESISTOR_AS_PULLUP(2,1); \
PORT2_INTERRUPT_PIN_ON_NEG_EDGE(1); \
ENABLE_PORT2_INTERRUPTS_PIN(1); \
CLEAR_PORT2_FLAG_PIN(1);
#define CONFIGURE_INTERRUPT_SWITCH1_ON_RELEASE SET_GPIO_RESISTOR_AS_PULLUP(2,1); \
   PORT2_INTERRUPT_PIN_ON_POS_EDGE(1); \
   ENABLE_PORT2_INTERRUPTS_PIN(1); \
   CLEAR_PORT2_FLAG_PIN(1);
#define CONFIGURE_INTERRUPT_SWITCH2_ON_PRESS SET_GPIO_RESISTOR_AS_PULLUP(1,1); \
PORT1_INTERRUPT_PIN_ON_NEG_EDGE(1); \
ENABLE_PORT1_INTERRUPTS_PIN(1);\
CLEAR_PORT1_FLAG_PIN(1);
#define CONFIGURE_INTERRUPT_SWITCH2_ON_RELEASE SET_GPIO_RESISTOR_AS_PULLUP(1,1); \
   PORT1_INTERRUPT_PIN_ON_POS_EDGE(1); \
   ENABLE_PORT1_INTERRUPTS_PIN(1); \
   CLEAR_PORT1_FLAG_PIN(1);
// LEDS - left LED1 (red) pin 1.0 and right LED2 (green) is pin 4.7
   #define CONFIGURE_LED1 SET_GPIO_AS_OUTPUT(1,0); \
  SET_GPIO_OUTPUT_LOW(1,0);
   #define CONFIGURE_LED2 SET_GPIO_AS_OUTPUT(4,7); \
  SET_GPIO_OUTPUT_LOW(4,7);
   #define TURN_LED1_ON SET_GPIO_OUTPUT_HIGH(1,0);
   #define TURN_LED1_OFF SET_GPIO_OUTPUT_LOW(1,0);
   #define TOGGLE_LED1 TOGGLE_GPIO_OUTPUT(1,0);
   #define TURN_LED2_ON SET_GPIO_OUTPUT_HIGH(4,7);
   #define TURN_LED2_OFF SET_GPIO_OUTPUT_LOW(4,7);
   #define TOGGLE_LED2 TOGGLE_GPIO_OUTPUT(4,7); 
// GPIO - SET AS INPUTS
  // Left Set of Pins
      // Left Column
      #define SET_PORT6_PIN5_GPIO_INPUT SET_GPIO_AS_INPUT(6,5);
      #define SET_PORT3_PIN4_GPIO_INPUT SET_GPIO_AS_INPUT(3,4);
      #define SET_PORT3_PIN3_GPIO_INPUT SET_GPIO_AS_INPUT(3,3);
      #define SET_PORT1_PIN6_GPIO_INPUT SET_GPIO_AS_INPUT(1,6);
      #define SET_PORT6_PIN6_GPIO_INPUT SET_GPIO_AS_INPUT(6,6);
      #define SET_PORT3_PIN2_GPIO_INPUT SET_GPIO_AS_INPUT(3,2);
      #define SET_PORT2_PIN7_GPIO_INPUT SET_GPIO_AS_INPUT(2,7);
      #define SET_PORT4_PIN2_GPIO_INPUT SET_GPIO_AS_INPUT(4,2);
      #define SET_PORT4_PIN1_GPIO_INPUT SET_GPIO_AS_INPUT(4,1);
      // Right Column
      #define SET_PORT6_PIN0_GPIO_INPUT SET_GPIO_AS_INPUT(6,0);
      #define SET_PORT6_PIN1_GPIO_INPUT SET_GPIO_AS_INPUT(6,1);
      #define SET_PORT6_PIN2_GPIO_INPUT SET_GPIO_AS_INPUT(6,2);
      #define SET_PORT6_PIN3_GPIO_INPUT SET_GPIO_AS_INPUT(6,3);
      #define SET_PORT6_PIN4_GPIO_INPUT SET_GPIO_AS_INPUT(6,4);
      #define SET_PORT7_PIN0_GPIO_INPUT SET_GPIO_AS_INPUT(7,0);
      #define SET_PORT3_PIN6_GPIO_INPUT SET_GPIO_AS_INPUT(3,6);
      #define SET_PORT3_PIN5_GPIO_INPUT SET_GPIO_AS_INPUT(3,5);
// Right Set of Pins
// Left Column
#define SET_PORT2_PIN5_GPIO_INPUT SET_GPIO_AS_INPUT(2,5);
#define SET_PORT2_PIN4_GPIO_INPUT SET_GPIO_AS_INPUT(2,4);
#define SET_PORT1_PIN5_GPIO_INPUT SET_GPIO_AS_INPUT(1,5);
#define SET_PORT1_PIN4_GPIO_INPUT SET_GPIO_AS_INPUT(1,4);
#define SET_PORT1_PIN3_GPIO_INPUT SET_GPIO_AS_INPUT(1,3);
#define SET_PORT1_PIN2_GPIO_INPUT SET_GPIO_AS_INPUT(1,2);
#define SET_PORT4_PIN3_GPIO_INPUT SET_GPIO_AS_INPUT(4,3);
#define SET_PORT4_PIN0_GPIO_INPUT SET_GPIO_AS_INPUT(4,0);
#define SET_PORT3_PIN7_GPIO_INPUT SET_GPIO_AS_INPUT(3,7);
#define SET_PORT8_PIN2_GPIO_INPUT SET_GPIO_AS_INPUT(8,2);
  // Right Column
#define SET_PORT2_PIN0_GPIO_INPUT SET_GPIO_AS_INPUT(2,0);
#define SET_PORT2_PIN2_GPIO_INPUT SET_GPIO_AS_INPUT(2,2);
#define SET_PORT7_PIN4_GPIO_INPUT SET_GPIO_AS_INPUT(7,4);
//RST PIN?
#define SET_PORT3_PIN0_GPIO_INPUT SET_GPIO_AS_INPUT(3,0);
#define SET_PORT3_PIN1_GPIO_INPUT SET_GPIO_AS_INPUT(3,1);
#define SET_PORT2_PIN6_GPIO_INPUT SET_GPIO_AS_INPUT(2,6);
#define SET_PORT2_PIN3_GPIO_INPUT SET_GPIO_AS_INPUT(2,3);
#define SET_PORT8_PIN1_GPIO_INPUT SET_GPIO_AS_INPUT(8,1);
// GPIO - SET AS OUTPUTS
  // Left Set of Pins
      // Left Column
      #define SET_PORT6_PIN5_GPIO_OUTPUT SET_GPIO_AS_OUTPUT(6,5);
      #define SET_PORT3_PIN4_GPIO_OUTPUT SET_GPIO_AS_OUTPUT(3,4);
      #define SET_PORT3_PIN3_GPIO_OUTPUT SET_GPIO_AS_OUTPUT(3,3);
      #define SET_PORT1_PIN6_GPIO_OUTPUT SET_GPIO_AS_OUTPUT(1,6);
      #define SET_PORT6_PIN6_GPIO_OUTPUT SET_GPIO_AS_OUTPUT(6,6);
      #define SET_PORT3_PIN2_GPIO_OUTPUT SET_GPIO_AS_OUTPUT(3,2);
      #define SET_PORT2_PIN7_GPIO_OUTPUT SET_GPIO_AS_OUTPUT(2,7);
      #define SET_PORT4_PIN2_GPIO_OUTPUT SET_GPIO_AS_OUTPUT(4,2);
      #define SET_PORT4_PIN1_GPIO_OUTPUT SET_GPIO_AS_OUTPUT(4,1);
      // Right Column
      #define SET_PORT6_PIN0_GPIO_OUTPUT SET_GPIO_AS_OUTPUT(6,0);
      #define SET_PORT6_PIN1_GPIO_OUTPUT SET_GPIO_AS_OUTPUT(6,1);
      #define SET_PORT6_PIN2_GPIO_OUTPUT SET_GPIO_AS_OUTPUT(6,2);
      #define SET_PORT6_PIN3_GPIO_OUTPUT SET_GPIO_AS_OUTPUT(6,3);
      #define SET_PORT6_PIN4_GPIO_OUTPUT SET_GPIO_AS_OUTPUT(6,4);
      #define SET_PORT7_PIN0_GPIO_OUTPUT SET_GPIO_AS_OUTPUT(7,0);
      #define SET_PORT3_PIN6_GPIO_OUTPUT SET_GPIO_AS_OUTPUT(3,6);
      #define SET_PORT3_PIN5_GPIO_OUTPUT SET_GPIO_AS_OUTPUT(3,5);
// Right Set of Pins
// Left Column
#define SET_PORT2_PIN5_GPIO_OUTPUT SET_GPIO_AS_OUTPUT(2,5);
#define SET_PORT2_PIN4_GPIO_OUTPUT SET_GPIO_AS_OUTPUT(2,4);
#define SET_PORT1_PIN5_GPIO_OUTPUT SET_GPIO_AS_OUTPUT(1,5);
#define SET_PORT1_PIN4_GPIO_OUTPUT SET_GPIO_AS_OUTPUT(1,4);
#define SET_PORT1_PIN3_GPIO_OUTPUT SET_GPIO_AS_OUTPUT(1,3);
#define SET_PORT1_PIN2_GPIO_OUTPUT SET_GPIO_AS_OUTPUT(1,2);
#define SET_PORT4_PIN3_GPIO_OUTPUT SET_GPIO_AS_OUTPUT(4,3);
#define SET_PORT4_PIN0_GPIO_OUTPUT SET_GPIO_AS_OUTPUT(4,0);
#define SET_PORT3_PIN7_GPIO_OUTPUT SET_GPIO_AS_OUTPUT(3,7);
#define SET_PORT8_PIN2_GPIO_OUTPUT SET_GPIO_AS_OUTPUT(8,2);
  // Right Column
#define SET_PORT2_PIN0_GPIO_OUTPUT SET_GPIO_AS_OUTPUT(2,0);
#define SET_PORT2_PIN2_GPIO_OUTPUT SET_GPIO_AS_OUTPUT(2,2);
#define SET_PORT7_PIN4_GPIO_OUTPUT SET_GPIO_AS_OUTPUT(7,4);
//RST PIN?
#define SET_PORT3_PIN0_GPIO_OUTPUT SET_GPIO_AS_OUTPUT(3,0);
#define SET_PORT3_PIN1_GPIO_OUTPUT SET_GPIO_AS_OUTPUT(3,1);
#define SET_PORT2_PIN6_GPIO_OUTPUT SET_GPIO_AS_OUTPUT(2,6);
#define SET_PORT2_PIN3_GPIO_OUTPUT SET_GPIO_AS_OUTPUT(2,3);
#define SET_PORT8_PIN1_GPIO_OUTPUT SET_GPIO_AS_OUTPUT(8,1);
// GPIO - Enable Interrupts
// Left Set of Pins
// Left Column
#define ENABLE_GPIO_INTERRUPTS_PORT1_PIN6 ENABLE_PORT1_INTERRUPTS_PIN(6); \
        CLEAR_PORT1_FLAG_PIN(6);
#define ENABLE_GPIO_INTERRUPTS_PORT2_PIN7 ENABLE_PORT2_INTERRUPTS_PIN(7); \
        CLEAR_PORT2_FLAG_PIN(7);
// Right Column
// Right Set of Pins
// Left Column
#define ENABLE_GPIO_INTERRUPTS_PORT2_PIN5 ENABLE_PORT2_INTERRUPTS_PIN(5); \
        CLEAR_PORT2_FLAG_PIN(5);
#define ENABLE_GPIO_INTERRUPTS_PORT2_PIN4 ENABLE_PORT2_INTERRUPTS_PIN(4); \
      CLEAR_PORT2_FLAG_PIN(4);
#define ENABLE_GPIO_INTERRUPTS_PORT1_PIN5 ENABLE_PORT1_INTERRUPTS_PIN(5); \
        CLEAR_PORT1_FLAG_PIN(5);
#define ENABLE_GPIO_INTERRUPTS_PORT1_PIN4 ENABLE_PORT1_INTERRUPTS_PIN(4); \
        CLEAR_PORT1_FLAG_PIN(4);
#define ENABLE_GPIO_INTERRUPTS_PORT1_PIN3 ENABLE_PORT1_INTERRUPTS_PIN(3); \
        CLEAR_PORT1_FLAG_PIN(3);
#define ENABLE_GPIO_INTERRUPTS_PORT1_PIN2 ENABLE_PORT1_INTERRUPTS_PIN(2); \
        CLEAR_PORT1_FLAG_PIN(2);
// Right Column
#define ENABLE_GPIO_INTERRUPTS_PORT2_PIN0 ENABLE_PORT2_INTERRUPTS_PIN(0); \
        CLEAR_PORT2_FLAG_PIN(0);
#define ENABLE_GPIO_INTERRUPTS_PORT2_PIN2 ENABLE_PORT2_INTERRUPTS_PIN(2); \
        CLEAR_PORT2_FLAG_PIN(2);
#define ENABLE_GPIO_INTERRUPTS_PORT2_PIN6 ENABLE_PORT2_INTERRUPTS_PIN(6); \
        CLEAR_PORT2_FLAG_PIN(6);
#define ENABLE_GPIO_INTERRUPTS_PORT2_PIN3 ENABLE_PORT2_INTERRUPTS_PIN(3); \
        CLEAR_PORT2_FLAG_PIN(3);
// GPIO - Disable Interrupts
// Left Set of Pins
// Left Column
#define DISABLE_GPIO_INTERRUPTS_PORT1_PIN6 DISABLE_PORT1_INTERRUPTS_PIN(6); \
             CLEAR_PORT1_FLAG_PIN(6);
#define DISABLE_GPIO_INTERRUPTS_PORT2_PIN7 DISABLE_PORT2_INTERRUPTS_PIN(7); \
             CLEAR_PORT2_FLAG_PIN(7);
// Right Column
// Right Set of Pins
// Left Column
#define DISABLE_GPIO_INTERRUPTS_PORT2_PIN5 DISABLE_PORT2_INTERRUPTS_PIN(5); \
             CLEAR_PORT2_FLAG_PIN(5);
#define DISABLE_GPIO_INTERRUPTS_PORT2_PIN4 DISABLE_PORT2_INTERRUPTS_PIN(4); \
             CLEAR_PORT2_FLAG_PIN(4);
#define DISABLE_GPIO_INTERRUPTS_PORT1_PIN5 DISABLE_PORT1_INTERRUPTS_PIN(5); \
             CLEAR_PORT1_FLAG_PIN(5);
#define DISABLE_GPIO_INTERRUPTS_PORT1_PIN4 DISABLE_PORT1_INTERRUPTS_PIN(4); \
             CLEAR_PORT1_FLAG_PIN(4);
#define DISABLE_GPIO_INTERRUPTS_PORT1_PIN3 DISABLE_PORT1_INTERRUPTS_PIN(3); \
             CLEAR_PORT1_FLAG_PIN(3);
#define DISABLE_GPIO_INTERRUPTS_PORT1_PIN2 DISABLE_PORT1_INTERRUPTS_PIN(2); \
             CLEAR_PORT1_FLAG_PIN(2);
// Right Column
#define DISABLE_GPIO_INTERRUPTS_PORT2_PIN0 DISABLE_PORT2_INTERRUPTS_PIN(0); \
             CLEAR_PORT2_FLAG_PIN(0);
#define DISABLE_GPIO_INTERRUPTS_PORT2_PIN2 DISABLE_PORT2_INTERRUPTS_PIN(2); \
             CLEAR_PORT2_FLAG_PIN(2);
#define DISABLE_GPIO_INTERRUPTS_PORT2_PIN6 DISABLE_PORT2_INTERRUPTS_PIN(6); \
             CLEAR_PORT2_FLAG_PIN(6);
#define DISABLE_GPIO_INTERRUPTS_PORT2_PIN3 DISABLE_PORT2_INTERRUPTS_PIN(3); \
             CLEAR_PORT2_FLAG_PIN(3);
// GPIO - Interrupt On Positive Edge
// Left Set of Pins
// Left Column
#define INTERRUPT_PORT1_PIN6_GPIO_ON_POS_EDGE PORT1_INTERRUPT_PIN_ON_POS_EDGE(6);
#define INTERRUPT_PORT2_PIN7_GPIO_ON_POS_EDGE PORT2_INTERRUPT_PIN_ON_POS_EDGE(7);
// Right Column
// Right Set of Pins
// Left Column
#define INTERRUPT_PORT2_PIN5_GPIO_ON_POS_EDGE PORT2_INTERRUPT_PIN_ON_POS_EDGE(5);
#define INTERRUPT_PORT2_PIN4_GPIO_ON_POS_EDGE PORT2_INTERRUPT_PIN_ON_POS_EDGE(4);
#define INTERRUPT_PORT1_PIN5_GPIO_ON_POS_EDGE PORT1_INTERRUPT_PIN_ON_POS_EDGE(5);
#define INTERRUPT_PORT1_PIN4_GPIO_ON_POS_EDGE PORT1_INTERRUPT_PIN_ON_POS_EDGE(4);
#define INTERRUPT_PORT1_PIN3_GPIO_ON_POS_EDGE PORT1_INTERRUPT_PIN_ON_POS_EDGE(3);
#define INTERRUPT_PORT1_PIN2_GPIO_ON_POS_EDGE PORT1_INTERRUPT_PIN_ON_POS_EDGE(2);
// Right Column
#define INTERRUPT_PORT2_PIN0_GPIO_ON_POS_EDGE PORT2_INTERRUPT_PIN_ON_POS_EDGE(0);
#define INTERRUPT_PORT2_PIN2_GPIO_ON_POS_EDGE PORT2_INTERRUPT_PIN_ON_POS_EDGE(2);
#define INTERRUPT_PORT2_PIN6_GPIO_ON_POS_EDGE PORT2_INTERRUPT_PIN_ON_POS_EDGE(6);
#define INTERRUPT_PORT2_PIN3_GPIO_ON_POS_EDGE PORT2_INTERRUPT_PIN_ON_POS_EDGE(3);
// GPIO - Interrupt On Negative Edge
// Left Set of Pins
// Left Column
#define INTERRUPT_PORT1_PIN6_GPIO_ON_NEG_EDGE PORT1_INTERRUPT_PIN_ON_NEG_EDGE(6);
#define INTERRUPT_PORT2_PIN7_GPIO_ON_NEG_EDGE PORT2_INTERRUPT_PIN_ON_NEG_EDGE(7);
// Right Column
// Right Set of Pins
// Left Column
#define INTERRUPT_PORT2_PIN5_GPIO_ON_NEG_EDGE PORT2_INTERRUPT_PIN_ON_NEG_EDGE(5);
#define INTERRUPT_PORT2_PIN4_GPIO_ON_NEG_EDGE PORT2_INTERRUPT_PIN_ON_NEG_EDGE(4);
#define INTERRUPT_PORT1_PIN5_GPIO_ON_NEG_EDGE PORT1_INTERRUPT_PIN_ON_NEG_EDGE(5);
#define INTERRUPT_PORT1_PIN4_GPIO_ON_NEG_EDGE PORT1_INTERRUPT_PIN_ON_NEG_EDGE(4);
#define INTERRUPT_PORT1_PIN3_GPIO_ON_NEG_EDGE PORT1_INTERRUPT_PIN_ON_NEG_EDGE(3);
#define INTERRUPT_PORT1_PIN2_GPIO_ON_NEG_EDGE PORT1_INTERRUPT_PIN_ON_NEG_EDGE(2);
// Right Column
#define INTERRUPT_PORT2_PIN0_GPIO_ON_NEG_EDGE PORT2_INTERRUPT_PIN_ON_NEG_EDGE(0);
#define INTERRUPT_PORT2_PIN2_GPIO_ON_NEG_EDGE PORT2_INTERRUPT_PIN_ON_NEG_EDGE(2);
#define INTERRUPT_PORT2_PIN6_GPIO_ON_NEG_EDGE PORT2_INTERRUPT_PIN_ON_NEG_EDGE(6);
#define INTERRUPT_PORT2_PIN3_GPIO_ON_NEG_EDGE PORT2_INTERRUPT_PIN_ON_NEG_EDGE(3);  
// GPIO - SET OUTPUT HIGH
  // Left Set of Pins
      // Left Column
      #define SET_PORT6_PIN5_GPIO_OUTPUT_HIGH SET_GPIO_OUTPUT_HIGH(6,5);
      #define SET_PORT3_PIN4_GPIO_OUTPUT_HIGH SET_GPIO_OUTPUT_HIGH(3,4);
      #define SET_PORT3_PIN3_GPIO_OUTPUT_HIGH SET_GPIO_OUTPUT_HIGH(3,3);
      #define SET_PORT1_PIN6_GPIO_OUTPUT_HIGH SET_GPIO_OUTPUT_HIGH(1,6);
      #define SET_PORT6_PIN6_GPIO_OUTPUT_HIGH SET_GPIO_OUTPUT_HIGH(6,6);
      #define SET_PORT3_PIN2_GPIO_OUTPUT_HIGH SET_GPIO_OUTPUT_HIGH(3,2);
      #define SET_PORT2_PIN7_GPIO_OUTPUT_HIGH SET_GPIO_OUTPUT_HIGH(2,7);
      #define SET_PORT4_PIN2_GPIO_OUTPUT_HIGH SET_GPIO_OUTPUT_HIGH(4,2);
      #define SET_PORT4_PIN1_GPIO_OUTPUT_HIGH SET_GPIO_OUTPUT_HIGH(4,1);
      // Right Column
      #define SET_PORT6_PIN0_GPIO_OUTPUT_HIGH SET_GPIO_OUTPUT_HIGH(6,0);
      #define SET_PORT6_PIN1_GPIO_OUTPUT_HIGH SET_GPIO_OUTPUT_HIGH(6,1);
      #define SET_PORT6_PIN2_GPIO_OUTPUT_HIGH SET_GPIO_OUTPUT_HIGH(6,2);
      #define SET_PORT6_PIN3_GPIO_OUTPUT_HIGH SET_GPIO_OUTPUT_HIGH(6,3);
      #define SET_PORT6_PIN4_GPIO_OUTPUT_HIGH SET_GPIO_OUTPUT_HIGH(6,4);
      #define SET_PORT7_PIN0_GPIO_OUTPUT_HIGH SET_GPIO_OUTPUT_HIGH(7,0);
      #define SET_PORT3_PIN6_GPIO_OUTPUT_HIGH SET_GPIO_OUTPUT_HIGH(3,6);
      #define SET_PORT3_PIN5_GPIO_OUTPUT_HIGH SET_GPIO_OUTPUT_HIGH(3,5);
// Right Set of Pins
// Left Column
#define SET_PORT2_PIN5_GPIO_OUTPUT_HIGH SET_GPIO_OUTPUT_HIGH(2,5);
#define SET_PORT2_PIN4_GPIO_OUTPUT_HIGH SET_GPIO_OUTPUT_HIGH(2,4);
#define SET_PORT1_PIN5_GPIO_OUTPUT_HIGH SET_GPIO_OUTPUT_HIGH(1,5);
#define SET_PORT1_PIN4_GPIO_OUTPUT_HIGH SET_GPIO_OUTPUT_HIGH(1,4);
#define SET_PORT1_PIN3_GPIO_OUTPUT_HIGH SET_GPIO_OUTPUT_HIGH(1,3);
#define SET_PORT1_PIN2_GPIO_OUTPUT_HIGH SET_GPIO_OUTPUT_HIGH(1,2);
#define SET_PORT4_PIN3_GPIO_OUTPUT_HIGH SET_GPIO_OUTPUT_HIGH(4,3);
#define SET_PORT4_PIN0_GPIO_OUTPUT_HIGH SET_GPIO_OUTPUT_HIGH(4,0);
#define SET_PORT3_PIN7_GPIO_OUTPUT_HIGH SET_GPIO_OUTPUT_HIGH(3,7);
#define SET_PORT8_PIN2_GPIO_OUTPUT_HIGH SET_GPIO_OUTPUT_HIGH(8,2);
  // Right Column
#define SET_PORT2_PIN0_GPIO_OUTPUT_HIGH SET_GPIO_OUTPUT_HIGH(2,0);
#define SET_PORT2_PIN2_GPIO_OUTPUT_HIGH SET_GPIO_OUTPUT_HIGH(2,2);
#define SET_PORT7_PIN4_GPIO_OUTPUT_HIGH SET_GPIO_OUTPUT_HIGH(7,4);
//RST PIN?
#define SET_PORT3_PIN0_GPIO_OUTPUT_HIGH SET_GPIO_OUTPUT_HIGH(3,0);
#define SET_PORT3_PIN1_GPIO_OUTPUT_HIGH SET_GPIO_OUTPUT_HIGH(3,1);
#define SET_PORT2_PIN6_GPIO_OUTPUT_HIGH SET_GPIO_OUTPUT_HIGH(2,6);
#define SET_PORT2_PIN3_GPIO_OUTPUT_HIGH SET_GPIO_OUTPUT_HIGH(2,3);
#define SET_PORT8_PIN1_GPIO_OUTPUT_HIGH SET_GPIO_OUTPUT_HIGH(8,1);
// GPIO - SET OUTPUT LOW
  // Left Set of Pins
      // Left Column
      #define SET_PORT6_PIN5_GPIO_OUTPUT_LOW SET_GPIO_OUTPUT_LOW(6,5);
      #define SET_PORT3_PIN4_GPIO_OUTPUT_LOW SET_GPIO_OUTPUT_LOW(3,4);
      #define SET_PORT3_PIN3_GPIO_OUTPUT_LOW SET_GPIO_OUTPUT_LOW(3,3);
      #define SET_PORT1_PIN6_GPIO_OUTPUT_LOW SET_GPIO_OUTPUT_LOW(1,6);
      #define SET_PORT6_PIN6_GPIO_OUTPUT_LOW SET_GPIO_OUTPUT_LOW(6,6);
      #define SET_PORT3_PIN2_GPIO_OUTPUT_LOW SET_GPIO_OUTPUT_LOW(3,2);
      #define SET_PORT2_PIN7_GPIO_OUTPUT_LOW SET_GPIO_OUTPUT_LOW(2,7);
      #define SET_PORT4_PIN2_GPIO_OUTPUT_LOW SET_GPIO_OUTPUT_LOW(4,2);
      #define SET_PORT4_PIN1_GPIO_OUTPUT_LOW SET_GPIO_OUTPUT_LOW(4,1);
      // Right Column
      #define SET_PORT6_PIN0_GPIO_OUTPUT_LOW SET_GPIO_OUTPUT_LOW(6,0);
      #define SET_PORT6_PIN1_GPIO_OUTPUT_LOW SET_GPIO_OUTPUT_LOW(6,1);
      #define SET_PORT6_PIN2_GPIO_OUTPUT_LOW SET_GPIO_OUTPUT_LOW(6,2);
      #define SET_PORT6_PIN3_GPIO_OUTPUT_LOW SET_GPIO_OUTPUT_LOW(6,3);
      #define SET_PORT6_PIN4_GPIO_OUTPUT_LOW SET_GPIO_OUTPUT_LOW(6,4);
      #define SET_PORT7_PIN0_GPIO_OUTPUT_LOW SET_GPIO_OUTPUT_LOW(7,0);
      #define SET_PORT3_PIN6_GPIO_OUTPUT_LOW SET_GPIO_OUTPUT_LOW(3,6);
      #define SET_PORT3_PIN5_GPIO_OUTPUT_LOW SET_GPIO_OUTPUT_LOW(3,5);
// Right Set of Pins
// Left Column
#define SET_PORT2_PIN5_GPIO_OUTPUT_LOW SET_GPIO_OUTPUT_LOW(2,5);
#define SET_PORT2_PIN4_GPIO_OUTPUT_LOW SET_GPIO_OUTPUT_LOW(2,4);
#define SET_PORT1_PIN5_GPIO_OUTPUT_LOW SET_GPIO_OUTPUT_LOW(1,5);
#define SET_PORT1_PIN4_GPIO_OUTPUT_LOW SET_GPIO_OUTPUT_LOW(1,4);
#define SET_PORT1_PIN3_GPIO_OUTPUT_LOW SET_GPIO_OUTPUT_LOW(1,3);
#define SET_PORT1_PIN2_GPIO_OUTPUT_LOW SET_GPIO_OUTPUT_LOW(1,2);
#define SET_PORT4_PIN3_GPIO_OUTPUT_LOW SET_GPIO_OUTPUT_LOW(4,3);
#define SET_PORT4_PIN0_GPIO_OUTPUT_LOW SET_GPIO_OUTPUT_LOW(4,0);
#define SET_PORT3_PIN7_GPIO_OUTPUT_LOW SET_GPIO_OUTPUT_LOW(3,7);
#define SET_PORT8_PIN2_GPIO_OUTPUT_LOW SET_GPIO_OUTPUT_LOW(8,2);
  // Right Column
#define SET_PORT2_PIN0_GPIO_OUTPUT_LOW SET_GPIO_OUTPUT_LOW(2,0);
#define SET_PORT2_PIN2_GPIO_OUTPUT_LOW SET_GPIO_OUTPUT_LOW(2,2);
#define SET_PORT7_PIN4_GPIO_OUTPUT_LOW SET_GPIO_OUTPUT_LOW(7,4);
//RST PIN?
#define SET_PORT3_PIN0_GPIO_OUTPUT_LOW SET_GPIO_OUTPUT_LOW(3,0);
#define SET_PORT3_PIN1_GPIO_OUTPUT_LOW SET_GPIO_OUTPUT_LOW(3,1);
#define SET_PORT2_PIN6_GPIO_OUTPUT_LOW SET_GPIO_OUTPUT_LOW(2,6);
#define SET_PORT2_PIN3_GPIO_OUTPUT_LOW SET_GPIO_OUTPUT_LOW(2,3);
#define SET_PORT8_PIN1_GPIO_OUTPUT_LOW SET_GPIO_OUTPUT_LOW(8,1);
// GPIO - TOGGLE OUTPUT
  // Left Set of Pins
      // Left Column
      #define TOGGLE_PORT6_PIN5_GPIO_OUTPUT TOGGLE_GPIO_OUTPUT(6,5);
      #define TOGGLE_PORT3_PIN4_GPIO_OUTPUT TOGGLE_GPIO_OUTPUT(3,4);
      #define TOGGLE_PORT3_PIN3_GPIO_OUTPUT TOGGLE_GPIO_OUTPUT(3,3);
      #define TOGGLE_PORT1_PIN6_GPIO_OUTPUT TOGGLE_GPIO_OUTPUT(1,6);
      #define TOGGLE_PORT6_PIN6_GPIO_OUTPUT TOGGLE_GPIO_OUTPUT(6,6);
      #define TOGGLE_PORT3_PIN2_GPIO_OUTPUT TOGGLE_GPIO_OUTPUT(3,2);
      #define TOGGLE_PORT2_PIN7_GPIO_OUTPUT TOGGLE_GPIO_OUTPUT(2,7);
      #define TOGGLE_PORT4_PIN2_GPIO_OUTPUT TOGGLE_GPIO_OUTPUT(4,2);
      #define TOGGLE_PORT4_PIN1_GPIO_OUTPUT TOGGLE_GPIO_OUTPUT(4,1);
      // Right Column
      #define TOGGLE_PORT6_PIN0_GPIO_OUTPUT TOGGLE_GPIO_OUTPUT(6,0);
      #define TOGGLE_PORT6_PIN1_GPIO_OUTPUT TOGGLE_GPIO_OUTPUT(6,1);
      #define TOGGLE_PORT6_PIN2_GPIO_OUTPUT TOGGLE_GPIO_OUTPUT(6,2);
      #define TOGGLE_PORT6_PIN3_GPIO_OUTPUT TOGGLE_GPIO_OUTPUT(6,3);
      #define TOGGLE_PORT6_PIN4_GPIO_OUTPUT TOGGLE_GPIO_OUTPUT(6,4);
      #define TOGGLE_PORT7_PIN0_GPIO_OUTPUT TOGGLE_GPIO_OUTPUT(7,0);
      #define TOGGLE_PORT3_PIN6_GPIO_OUTPUT TOGGLE_GPIO_OUTPUT(3,6);
      #define TOGGLE_PORT3_PIN5_GPIO_OUTPUT TOGGLE_GPIO_OUTPUT(3,5);
// Right Set of Pins
// Left Column
#define TOGGLE_PORT2_PIN5_GPIO_OUTPUT TOGGLE_GPIO_OUTPUT(2,5);
#define TOGGLE_PORT2_PIN4_GPIO_OUTPUT TOGGLE_GPIO_OUTPUT(2,4);
#define TOGGLE_PORT1_PIN5_GPIO_OUTPUT TOGGLE_GPIO_OUTPUT(1,5);
#define TOGGLE_PORT1_PIN4_GPIO_OUTPUT TOGGLE_GPIO_OUTPUT(1,4);
#define TOGGLE_PORT1_PIN3_GPIO_OUTPUT TOGGLE_GPIO_OUTPUT(1,3);
#define TOGGLE_PORT1_PIN2_GPIO_OUTPUT TOGGLE_GPIO_OUTPUT(1,2);
#define TOGGLE_PORT4_PIN3_GPIO_OUTPUT TOGGLE_GPIO_OUTPUT(4,3);
#define TOGGLE_PORT4_PIN0_GPIO_OUTPUT TOGGLE_GPIO_OUTPUT(4,0);
#define TOGGLE_PORT3_PIN7_GPIO_OUTPUT TOGGLE_GPIO_OUTPUT(3,7);
#define TOGGLE_PORT8_PIN2_GPIO_OUTPUT TOGGLE_GPIO_OUTPUT(8,2);
  // Right Column
#define TOGGLE_PORT2_PIN0_GPIO_OUTPUT TOGGLE_GPIO_OUTPUT(2,0);
#define TOGGLE_PORT2_PIN2_GPIO_OUTPUT TOGGLE_GPIO_OUTPUT(2,2);
#define TOGGLE_PORT7_PIN4_GPIO_OUTPUT TOGGLE_GPIO_OUTPUT(7,4);
//RST PIN?
#define TOGGLE_PORT3_PIN0_GPIO_OUTPUT TOGGLE_GPIO_OUTPUT(3,0);
#define TOGGLE_PORT3_PIN1_GPIO_OUTPUT TOGGLE_GPIO_OUTPUT(3,1);
#define TOGGLE_PORT2_PIN6_GPIO_OUTPUT TOGGLE_GPIO_OUTPUT(2,6);
#define TOGGLE_PORT2_PIN3_GPIO_OUTPUT TOGGLE_GPIO_OUTPUT(2,3);
#define TOGGLE_PORT8_PIN1_GPIO_OUTPUT TOGGLE_GPIO_OUTPUT(8,1);
    // ADC 12
    #define SET_PORT6_PIN5_ADC_A5 USE_GPIO_PERIPHERAL_AS_INPUT(6,5);
    #define SET_PORT6_PIN6_ADC_A6 USE_GPIO_PERIPHERAL_AS_INPUT(6,6);
    #define SET_PORT6_PIN0_ADC_A0 USE_GPIO_PERIPHERAL_AS_INPUT(6,0);
    #define SET_PORT6_PIN1_ADC_A1 USE_GPIO_PERIPHERAL_AS_INPUT(6,1);
    #define SET_PORT6_PIN2_ADC_A2 USE_GPIO_PERIPHERAL_AS_INPUT(6,2);
    #define SET_PORT6_PIN3_ADC_A3 USE_GPIO_PERIPHERAL_AS_INPUT(6,3);
    #define SET_PORT6_PIN4_ADC_A4 USE_GPIO_PERIPHERAL_AS_INPUT(6,4);
    #define SET_PORT7_PIN0_ADC_A12 USE_GPIO_PERIPHERAL_AS_INPUT(7,0);
    // Timers 
    // PWMs
        #define SET_PORT3_PIN6_TIMERB0_6_PWM_OUTPUT USE_GPIO_PERIPHERAL_AS_OUTPUT(3,6);
        #define SET_PORT3_PIN5_TIMERB0_5_PWM_OUTPUT USE_GPIO_PERIPHERAL_AS_OUTPUT(3,5);
        #define SET_PORT2_PIN0_TIMERA1_1_PWM_OUTPUT USE_GPIO_PERIPHERAL_AS_OUTPUT(2,0);
        #define SET_PORT7_PIN4_TIMERB0_2_PWM_OUTPUT USE_GPIO_PERIPHERAL_AS_OUTPUT(7,4);
        #define SET_PORT2_PIN3_TIMERA2_0_PWM_OUTPUT USE_GPIO_PERIPHERAL_AS_OUTPUT(2,3);
        #define SET_PORT2_PIN5_TIMERA2_2_PWM_OUTPUT USE_GPIO_PERIPHERAL_AS_OUTPUT(2,5);
        #define SET_PORT2_PIN3_TIMERA2_1_PWM_OUTPUT USE_GPIO_PERIPHERAL_AS_OUTPUT(2,3);
        #define SET_PORT1_PIN3_TIMERA0_2_PWM_OUTPUT USE_GPIO_PERIPHERAL_AS_OUTPUT(1,3);
        #define SET_PORT1_PIN2_TIMERA0_1_PWM_OUTPUT USE_GPIO_PERIPHERAL_AS_OUTPUT(1,2);
    // Timer Captures
    #define SET_PORT3_PIN6_TIMERB0_6_CAPTURE_INPUT USE_GPIO_PERIPHERAL_AS_INPUT(3,6);
#define SET_PORT3_PIN5_TIMERB0_5_CAPTURE_INPUT USE_GPIO_PERIPHERAL_AS_INPUT(3,5);
#define SET_PORT2_PIN0_TIMERA1_1_CAPTURE_INPUT USE_GPIO_PERIPHERAL_AS_INPUT(2,0);
#define SET_PORT7_PIN4_TIMERB0_2_CAPTURE_INPUT USE_GPIO_PERIPHERAL_AS_INPUT(7,4);
#define SET_PORT2_PIN3_TIMERA2_0_CAPTURE_INPUT USE_GPIO_PERIPHERAL_AS_INPUT(2,3);
#define SET_PORT2_PIN5_TIMERA2_2_CAPTURE_INPUT USE_GPIO_PERIPHERAL_AS_INPUT(2,5);
#define SET_PORT2_PIN3_TIMERA2_1_CAPTURE_INPUT USE_GPIO_PERIPHERAL_AS_INPUT(2,3);
#define SET_PORT1_PIN3_TIMERA0_2_CAPTURE_INPUT USE_GPIO_PERIPHERAL_AS_INPUT(1,3);
#define SET_PORT1_PIN2_TIMERA0_1_CAPTURE_INPUT USE_GPIO_PERIPHERAL_AS_INPUT(1,2);
    // Timer Clock Inputs
        #define SET_PORT2_PIN2_TA2CLK_INPUT USE_GPIO_PERIPHERAL_AS_INPUT(2,2);
        #define SET_PORT1_PIN6_TA1CLK_INPUT USE_GPIO_PERIPHERAL_AS_INPUT(1,6);              
#endif // _DevelopmentBoardMacros_


Which I then use to build some basic timer set up macros

Code: [Select]
#ifndef _TimerMacros_
#define _TimerMacros_
#include <msp430.h>
// Timer A (Consists of Timers A0,A1,A2. So x can be 0 OR 1 OR 2)
// TAxCTL: Timer_Ax Control Register(x can be: 0 OR 1 OR 2)
    // source can be: TACLK OR ACLK OR SMCLK OR INCLK
#define SET_TIMER_Ax_CLOCK_SOURCE(x,source) TA ## x ## CTL |= TASSEL__ ## source;
// divider can be: 1 OR 2 OR 3 OR 4 OR 8
#define SET_TIMER_Ax_INPUT_DIVIDER(x,divider) TA ## x ## CTL |= ID__ ## divider;
// mode can be: STOP OR UP OR CONTINUOUS OR UPDOWN
#define SET_TIMER_Ax_MODE_CONTROLER(x,mode) TA ## x ## CTL |= MC__ ## mode;
#define CLEAR_TIMER_Ax(x) TA ## x ## CTL |= TACLR;
#define ENABLE_INTERRUPTS_TIMER_Ax(x) TA ## x ## CTL |= TAIE;
#define DISABLE_INTERRUPTS_TIMER_Ax(x) TA ## x ## CTL &= ~TAIE;
#define CHECK_PENDING_INTERRUPT_TIMER_Ax(x) TA ## x ## CTL & TAIFG;
#define CLEAR_INTERRUPT_TIMER_Ax(x) TA ## x ## CTL &= ~TAIFG;
// TAxR: Timer_Ax Counter Register 
#define READ_TIMER_Ax_VALUE(x) TA ## x ## R;
#define OVERWRITE_TIMER_Ax_VALUE(x,overwrite) TA ## x ## R = overwrite;
#define CLEAR_TIMER_Ax_VALUE(x) TA ## x ## R = 0;
#define ADD_TO_TIMER_Ax_VALUE(x,addend) TA ## x ## R += addend;
#define SUBTRACT_FROM_TIMER_Ax_VALUE(x,subtrahend) TA ## x ## R -= subtrahend;
#define DIVIDE_TIMER_Ax_VALUE(x,divisor) TA ## x ## R /= divisor;
#define MULTIPLY_TIMER_Ax_VALUE(x,multiplicand) TA ## x ## R *= multiplicand;
// TAxCCTLn: Timer_Ax Capture/Compare Control n Register
#define SELECT_TIMER_Ax_CCRn_CAPTURE_MODE(x,n,mode) TA ## x CCTL ## n |=  CM_ ## mode;
#define SELECT_TIMER_Ax_CCRn_CC_INPUT(x,n,select) TA ## x CCTL ## n |=  CCIS_ ## select;
#define SYNCHRONOUS_TIMER_Ax_CCRn_CAPTURE(x,n) TA ## x CCTL ## n |= SCS;
#define ASYNCHRONOUS_TIMER_Ax_CCRn_CAPTURE(x,n) TA ## x CCTL ## n &= ~SCS;
#define SET_TIMER_Ax_CCRn_CAPTURE_MODE(x,n) TA ## x CCTL ## n |= CAP;
#define SET_TIMER_Ax_CCRn_COMPARE_MODE(x,n) TA ## x CCTL ## n &= ~CAP;
#define SELECT_TIMER_Ax_CCRn_OUTMOD(x,n,outputmode) TA ## x CCTL ## n |= OUTMOD_ ## outputmode;
#define ENABLE_TIMER_Ax_CCRn_INTERRUPT(x,n) TA ## x CCTL ## n |= CCIE;
#define DISABLE_TIMER_Ax_CCRn_INTERRUPT(x,n) TA ## x CCTL ## n &= ~CCIE;
#define READ_TIMER_Ax_CCRn_INPUT(x,n) TA ## x CCTL ## n & CCI;
#define SET_TIMER_Ax_CCRn_OUTPUT_HIGH(x,n) TA ## x CCTL ## n |= OUT;
#define SET_TIMER_Ax_CCRn_OUTPUT_LOW(x,n) TA ## x CCTL ## n &= ~OUT;
#define CHECK_TIMER_Ax_CCRn_CAPTURE_OVERFLOW(x,n) TA ## x CCTL ## n & COV;
#define CLEAR_TIMER_Ax_CCRn_CAPTURE_OVERFLOW(x,n) TA ## x CCTL ## n &= ~COV;
#define CHECK_TIMER_Ax_CCRn_INTERRUPT_FLAG(x,n) TA ## x CCTL ## n & CCIFG;
#define CLEAR_TIMER_Ax_CCRn_CCIFG(x,n) TA ## x CCTL ## n &= ~CCIFG;
// TAxCCRn: Timer_A Capture/Compare n Register
#define READ_TIMER_Ax_CCRn_VALUE(x,n) TA ## x ## CCR ## n ## ;
#define OVER_TIMER_Ax_CCRn_VALUE(x,n,overwrite) TA ## x ## CCR ## n = overwrite;
#define CLEAR_TIMER_Ax_CCRn_VALUE(x,n) TA ## x ## CCR ## n = 0;
#define ADD_TO_TIMER_Ax_CCRn_VALUE(x,n,addend) TA ## x ## CCR ## n += addend;
#define SUBTRACT_FROM_TIMER_Ax_CCRn_VALUE(x,n,subtrahend) TA ## x ## CCR ## n -= subtrahend;
#define MULTIPLY_TIMER_Ax_CCRn_VALUE(x,n,multiplicand) TA ## x ## CCR ## n *= multiplicand;
#define DIVIDE_TIMER_Ax_CCRn_VALUE(x,n,divisor) TA ## x ## CCR ## n /= divisor;
// TAxIV: Timer_Ax Interrupt Vector Register
#define
// TAxEX0: Timer_Ax Expansion 0 Register



#endif



of course the tabs are messed up
 

Online brucehoult

  • Super Contributor
  • ***
  • Posts: 4034
  • Country: nz
Re: [gcc C] concatenating text to make up code
« Reply #174 on: October 18, 2018, 02:35:49 am »
This is out of their header:
I know. Do you see the difference between
Code: [Select]
#define PORTA (PORT_t *)0x0400
and
Code: [Select]
#define PORTA                (*(PORT_t *) 0x0400)
?

All you really need is the former. And that's what ARM files have.
If you define that, for example like this:

Code: [Select]
#define MY_PORTA (PORT_t *)0x0400

Then you will be able to create universal functions like this:

Code: [Select]
void out_set(PORT_t *port, int pin)
{
  port->OUTSET = (1<<pin);
}

What else do you need?

You can use that function perfectly well even with the pre-dereferenced #defines like "#define PORTA (*(PORT_t *) 0x0400)"

Code: [Select]
void do_it(){
    out_set(&PORTA, 3);
}

If you're using C++ then it's a little bit tidier to make the function take a reference instead:

Code: [Select]
void out_set(PORT_t &port, int pin){
  port->OUTSET = (1<<pin);
}

void do_it(){
  out_set(PORTA, 3);
}
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf