#include "stm32c0xx_hal.h"
GPIO_TypeDef* ledPorts[] = {GPIOB, GPIOB, GPIOB, GPIOB, GPIOA};
uint16_t ledPins[] = {GPIO_PIN_3, GPIO_PIN_10, GPIO_PIN_4, GPIO_PIN_5, GPIO_PIN_15};
const int totalLEDs = 5;
const int winLedPinIndex = 2; // LED urutan ke-3 = PB4 (D5), komponen led4
int delayTime = 100;
int level = 1;
const int maxLevel = 5;
volatile bool holdLEDState = false;
volatile int activeLEDIndex = -1;
volatile int lastLEDIndex = -1;
volatile bool acceptingPress = false;
volatile uint32_t lastPressTime = 0;
enum GameState { IDLE, RUNNING, WIN, LOSE };
GameState currentState = IDLE;
uint32_t ledStartedAt = 0;
uint32_t resultStartedAt = 0;
void setRGBColor(GPIO_PinState red, GPIO_PinState blue) {
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_7, red);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, blue);
}
void allLEDsOff() {
for (int i = 0; i < totalLEDs; i++)
HAL_GPIO_WritePin(ledPorts[i], ledPins[i], GPIO_PIN_RESET);
}
void holdLEDs() {
uint32_t now = HAL_GetTick();
if (acceptingPress && !holdLEDState && activeLEDIndex >= 0 &&
(uint32_t)(now - lastPressTime) >= 30) {
lastPressTime = now;
lastLEDIndex = activeLEDIndex;
holdLEDState = true;
}
}
void setup() {
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
GPIO_InitTypeDef gpio = {0};
gpio.Mode = GPIO_MODE_OUTPUT_PP;
gpio.Pull = GPIO_NOPULL;
gpio.Speed = GPIO_SPEED_FREQ_LOW;
for (int i = 0; i < totalLEDs; i++) {
gpio.Pin = ledPins[i];
HAL_GPIO_Init(ledPorts[i], &gpio);
}
gpio.Pin = GPIO_PIN_7 | GPIO_PIN_5;
HAL_GPIO_Init(GPIOA, &gpio);
pinMode(D2, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(D2), holdLEDs, FALLING);
Serial.begin(115200);
setRGBColor(GPIO_PIN_SET, GPIO_PIN_SET);
Serial.println("Target: LED ke-3 / PB4 / D5");
}
void loop() {
uint32_t now = HAL_GetTick();
switch (currentState) {
case IDLE:
if (digitalRead(D2) == LOW) break; // tunggu tombol dilepas
noInterrupts();
acceptingPress = false;
holdLEDState = false;
lastLEDIndex = -1;
allLEDsOff();
activeLEDIndex = 0;
HAL_GPIO_WritePin(ledPorts[0], ledPins[0], GPIO_PIN_SET);
ledStartedAt = now;
currentState = RUNNING;
acceptingPress = true;
interrupts();
setRGBColor(GPIO_PIN_SET, GPIO_PIN_SET);
break;
case RUNNING:
noInterrupts();
if (holdLEDState) {
acceptingPress = false;
currentState = lastLEDIndex == winLedPinIndex ? WIN : LOSE;
resultStartedAt = now;
interrupts();
// RGB common anode: LOW menyalakan kanal warna.
if (currentState == WIN) setRGBColor(GPIO_PIN_RESET, GPIO_PIN_SET);
else setRGBColor(GPIO_PIN_SET, GPIO_PIN_RESET);
Serial.print(currentState == WIN ? "WIN" : "LOSE");
Serial.print(" LED="); Serial.print(lastLEDIndex + 1);
Serial.print(" level="); Serial.println(level);
} else {
if ((uint32_t)(now - ledStartedAt) >= (uint32_t)delayTime) {
HAL_GPIO_WritePin(ledPorts[activeLEDIndex], ledPins[activeLEDIndex], GPIO_PIN_RESET);
activeLEDIndex = (activeLEDIndex + 1) % totalLEDs;
HAL_GPIO_WritePin(ledPorts[activeLEDIndex], ledPins[activeLEDIndex], GPIO_PIN_SET);
ledStartedAt = now;
}
interrupts();
}
break;
case WIN:
case LOSE:
if ((uint32_t)(now - resultStartedAt) >= 1000) {
if (currentState == WIN && level < maxLevel) {
level++;
delayTime -= 20;
}
currentState = IDLE;
}
break;
}
}
Loading
st-nucleo-c031c6
st-nucleo-c031c6