Search code examples
c++pointersavrbitmaskatmega

Masking a Register Using Its Pointer - AVR Ports


I'm programming a Simon Says game with a microprocessor (atmega32) using some LEDs and buttons. I am trying to store the pointers to a PORT register in an array, which a function will use to mask the register (to turn the pins on to light the LED) depending on which button is pressed.

Something along the lines of

*arrayOfPointers[1] |= 1 << mask;

But I don't think this is working, and I think it is because I don't completely understand how masking or pointers work.

How do I mask a register, when I have the pointer to this register stored in an array of pointers? Please note I am a beginner/novice, so please explain like I'm stupid.

Here is a simplified sample of the relevant code:

volatile uint8_t *portActivate[numberOfButtons]; //stores pointers to the PORT register
unsigned char pinActivate[numberOfButtons];  //stores the pin I want to turn on

//activateOnPress populates 2 arrays that stores the PORT and PIN corresponding to each button. (index 0 is for button 0, index 1 is for button 1, etc.)
//this will be used to tell the program which PORT and PIN to activate (output a voltage) when that button is pressed.
void activateOnPress(unsigned int buttonNumber, volatile uint8_t *activatePort, unsigned char activatePin){
    *portActivate[buttonNumber] = *activatePort;    //store the pointer to PORT register in an array
    pinActivate[buttonNumber] = activatePin;    //store the pin to be turned on at that port
}

//buttonListen will see if the specified button has been pressed (voltage on pin is 0)
//if it has, it will output a voltage to the associated pin given by my 2 arrays by masking the register pointed to by the *portActivate array.
void buttonListen(unsigned int buttonNumber,unsigned char buttonPort, unsigned char buttonPin){
    if(bit_is_clear(buttonPort, buttonPin)){    //bit_is_clear means the pin is showing 0V  
        *portActivate[buttonNumber] |= 1 << pinActivate[buttonIndex];  //this is the part thats not working!!!!
    }
}

int main(void){
    activateOnPress(1, &PORTB, PIN0);  //associate button 1 to PORT B, PIN 0, which I want to activate (output 5V) when this button is pressed

    while(1){
        buttonListen(1, PORTA, PIN1); //listen to PORT A, PIN 1. If it's pressed, then output a voltage to the port and pin associated with button 1.
    }
    return 0;
}

I would appreciate any help.


Solution

  • I've written many device drivers over the years. So, I think I see [at least one of] your problems.

    I had to do some style cleanup to eliminate long sidebar comments. Most style guides recommend no wider than 80. It makes the code hard to read. I had to do this so I could understand your logic.

    Also, you had two parallel arrays, indexed by button number. I merged these into a struct, which associates the data better.

    Anyway, here's the cleaned up code, with the bug fix (Hint: #if):

    struct portpin {
        // stores pointers to the PORT register
        volatile uint8_t *portActivate;
    
        // stores the pin I want to turn on
        unsigned char pinActivate;
    };
    typedef struct portpin portpin_t;
    
    portpin_t portlist[numberOfButtons];
    
    // activateOnPress populates 2 arrays that stores the PORT and PIN corresponding
    // to each button. (index 0 is for button 0, index 1 is for button 1, etc.)
    // this will be used to tell the program which PORT and PIN to activate (output
    // a voltage) when that button is pressed.
    void
    activateOnPress(unsigned int butno,volatile uint8_t *activatePort,
        unsigned char activatePin)
    {
        portpin_t *port;
    
        port = &portlist[butno];
    
        // store the pointer to PORT register in an array
    #if 0
        *port->portActivate = *activatePort;  // your code
    #else
        port->portActivate = activatePort;  // fixed code
    #endif
    
        // store the pin to be turned on at that port
        port->pinActivate = activatePin;
    }
    
    // buttonListen will see if the specified button has been pressed (voltage on
    // pin is 0) if it has, it will output a voltage to the associated pin given by
    // my 2 arrays by masking the register pointed to by the *portActivate array.
    void
    buttonListen(unsigned int butno,unsigned char buttonPort,
        unsigned char buttonPin)
    {
        portpin_t *port;
    
        port = &portlist[butno];
    
        // bit_is_clear means the pin is showing 0V  
        if (bit_is_clear(buttonPort, buttonPin)) {
            // this is the part thats not working!!!!
            *port->portActivate |= 1 << port->pinActivate;
        }
    }
    
    int
    main(void)
    {
    
        // associate button 1 to PORT B, PIN 0, which I want to activate (output 5V)
        // when this button is pressed
        activateOnPress(1, &PORTB, PIN0);
    
        // listen to PORT A, PIN 1. If it's pressed, then output a voltage to the
        // port and pin associated with button 1.
        while (1)
            buttonListen(1, PORTA, PIN1);
    
        return 0;
    }