Home > Software design >  My while loop is not breaking after my interrupt updates in C
My while loop is not breaking after my interrupt updates in C

Time:05-11

I am implementing simon says as a small weekly project for school. Using arduino Uno, I'm making 10 levels each level has an extra pattern inside. example: level 1: [1], level 2: [1,2], etc... I have three buttons on my shield. the interrupts work and everything is gucci. My problem here is in this snippet

bool readInput(uint8_t pattern[], uint8_t length)
{
    sei();
    uint8_t current = 0;
    while (current < length)
    {
        btnPushed = false;
        while (!btnPushed)
        {
#ifdef DEBUG
            _delay_ms(1);
#endif
        }
        printf("here");
        cli();
        _delay_ms(200);
        if (currentPushed == pattern[current])
        {
            printf("correct, you pushed %d\n", currentPushed);
        }
        else
        {
            printf("incorrect, lets try again\n");
            return false;
        }
    }
    btnPushed = false;
    return true;
}

so basically I set my buttonPushed to false, and start listening for interrupts, once its true after clicking, I expect to exit the loop and check the input, however my interrupt is correct and I get visual feedback with a light that lights up once i push a button.

this is my ISR

ISR(PCINT1_vect)
{
    uint8_t buttonCurr = currentButton();
    if (buttonCurr != -1)
    {
        if (!btn1Pushed && buttonCurr == 0)
        {
            btn1Pushed = true;
        }
        currentPushed = buttonCurr;
        blinkLed(currentPushed, 1);
        btnPushed = true;
    }
}

my current button returns 0-2 for buttons that are clicked, and -1 if nothing was clicked.

this is the rest of my code, which is working pretty much

int currentPushed = -1;
bool won;
bool btnPushed = false;
bool btn1Pushed = false;

ISR(PCINT1_vect)
{
    uint8_t buttonCurr = currentButton();
    if (buttonCurr != -1)
    {
        if (!btn1Pushed && buttonCurr == 0)
        {
            btn1Pushed = true;
        }
        currentPushed = buttonCurr;
        blinkLed(currentPushed, 1);
        btnPushed = true;
    }
}

int main(void)
{
    enableAllButtons();
    enableAllLeds();
    lightDownAllLeds();

    prepareButtonsForInterrupt();
    initUSART();
    init();

    play();
    if (won)
    {
        printf("Simon says you win");
    }
    else
    {
        printf("simon says do better");
    }
    return 0;
}

void init(void)
{
    printf("LETS PLAY SIMON SAYS\nPress button 1 to start!\n");

    int seed = 0;
    while (!btn1Pushed)
    {
        blinkLed(3, 4);
        seed  ;
    }
    srand(seed);

    printf("Get ready!\n");
    btnPushed = false;
    cli();
}

void createRandomPattern(uint8_t array[], uint8_t length)
{
    for (int i = 0; i < length; i  )
    {
        array[i] = rand() % 3;
    }
}

void play(uint8_t pattern[])
{
    uint8_t fullPattern[MAX_PATTERN_LENGTH];
    createRandomPattern(fullPattern, MAX_PATTERN_LENGTH);
    for (int i = 1; i <= MAX_PATTERN_LENGTH; i  )
    {
        printf("========LEVEL %d===========\n", i);
        playPuzzle(fullPattern, i);
#ifdef DEBUG
        printPuzzle(fullPattern, i);
#endif
        readInput(fullPattern, i) ?: i--;
    }
}

bool readInput(uint8_t pattern[], uint8_t length)
{
    sei();
    uint8_t current = 0;
    while (current < length)
    {
        btnPushed = false;
        while (!btnPushed)
        {
        }
        cli();
        if (currentPushed == pattern[current])
        {
            printf("correct, you pushed %d\n", currentPushed);
        }
        else
        {
            printf("incorrect, lets try again\n");
            return false;
        }
        current  ;
    }
    btnPushed = false;
    return true;
}

void printPuzzle(uint8_t pattern[], uint8_t length)
{
    printf("[ ");
    for (int i = 0; i < length; i  )
    {
        printf("%d ", pattern[i]);
    }
    printf("]\n");
}

void playPuzzle(uint8_t pattern[], uint8_t length)
{
    for (int i = 0; i < length; i  )
    {
        lightUpOneLed(pattern[i]);
        _delay_ms(500);
        lightDownOneLed(pattern[i]);
    }
}

CodePudding user response:

btnPushed is defined as bool btnPushed = false;.

So when you write:

    while (!btnPushed)
    {
#ifdef DEBUG
        _delay_ms(1);
#endif
    }

Nothing in the loop will change btnPushed so there is no point for the compiler to ever check btnPushed again. So what the compiler sees is this:

    if (!btnPushed)
        while(true)
        {
#ifdef DEBUG
            _delay_ms(1);
#endif
        }

You have to tell the compiler that the value of btnPushed will change unexpectantly when the interrupt fires by using:

volatile bool btnPushed = false;
  • Related