/** * @file main.c * @brief UART console, interrupt-driven 4×4 keypad input, and Morse LED blink on MSP430FR2355. * * Initializes peripheral modules and enters low-power mode, waking on keypress * interrupts to blink Morse code on LED and echo keys over UART. * * @date 2025-07-02 */ #include #include #include #include #include #include "keypad.h" #include "morse.h" /** UART port/pin definitions */ #define UART_TX_PORT GPIO_PORT_P1 /** UART TX port */ #define UART_TX_PIN GPIO_PIN2 /** UART TX pin */ #define UART_RX_PORT GPIO_PORT_P1 /** UART RX port */ #define UART_RX_PIN GPIO_PIN3 /**< UART RX pin */ /** UART baudrate configuration for 9600 @ 1MHz SMCLK */ #define BAUDRATE_PRESCL 6U /**< UCBR */ #define BAUDRATE_FIRSTM 8U /**< UCBRF */ #define BAUDRATE_SECONDM 0U /**< UCBRS */ /** On-board LED port and pin (used by Morse module) */ #define LED_PORT GPIO_PORT_P1 /**< On-board LED port */ #define LED_PIN GPIO_PIN0 /**< On-board LED pin */ /** Shared buffer for last key press and ready flag (set in ISR) */ volatile char g_lastKey = 0; /**< Last key pressed */ volatile bool g_keyReady = false; /**< Flag indicating key available */ /** * @brief Initialize UART module for console output at 9600 baud. */ static void initSerial(void) { EUSCI_A_UART_initParam uartCfg; /* Configure TX/RX pins for UART function */ GPIO_setAsPeripheralModuleFunctionInputPin( UART_TX_PORT | UART_RX_PORT, UART_TX_PIN | UART_RX_PIN, GPIO_PRIMARY_MODULE_FUNCTION ); /* Populate UART configuration structure */ uartCfg.selectClockSource = EUSCI_A_UART_CLOCKSOURCE_SMCLK; uartCfg.clockPrescalar = BAUDRATE_PRESCL; uartCfg.firstModReg = BAUDRATE_FIRSTM; uartCfg.secondModReg = BAUDRATE_SECONDM; uartCfg.parity = EUSCI_A_UART_NO_PARITY; uartCfg.msborLsbFirst = EUSCI_A_UART_LSB_FIRST; uartCfg.numberofStopBits = EUSCI_A_UART_ONE_STOP_BIT; uartCfg.uartMode = EUSCI_A_UART_MODE; uartCfg.overSampling = EUSCI_A_UART_OVERSAMPLING_BAUDRATE_GENERATION; /* Apply configuration and enable UART */ EUSCI_A_UART_init(EUSCI_A0_BASE, &uartCfg); EUSCI_A_UART_enable(EUSCI_A0_BASE); } /** * @brief Transmit a null-terminated string over UART. * @param s Pointer to string to send */ static void serialPrint(const char *s) { const char *ptr = s; while (*ptr) { /* Send next character */ EUSCI_A_UART_transmitData(EUSCI_A0_BASE, *ptr++); /* Wait until transmission completes */ while (EUSCI_A_UART_queryStatusFlags( EUSCI_A0_BASE, EUSCI_A_UART_BUSY)); } } /** * @brief Keypad callback invoked on key press interrupt. * @param key ASCII character of pressed key * * Stores key, sets ready flag, and blinks Morse code on LED. */ static void myKeyHandler(char key) { g_lastKey = key; g_keyReady = true; blinkMorseChar(key); } /** * @brief Main application entry point. * * Sets up GPIO, UART, keypad interrupts, and enters low-power loop. * On keypress, echoes key over UART. * * @return Never returns */ int main(void) { char buf[32]; int len; /* Stop watchdog and unlock GPIO pins */ WDT_A_hold(WDT_A_BASE); PMM_unlockLPM5(); /* Initialize on-board LED (used by Morse blinking) */ GPIO_setAsOutputPin(LED_PORT, LED_PIN); GPIO_setOutputLowOnPin(LED_PORT, LED_PIN); /* Initialize UART console */ initSerial(); serialPrint("Keypad + LED test starting...\r\n"); /* Initialize keypad interrupt driver */ initKeypadInterrupts(myKeyHandler); /* Enter low-power mode and wait for key interrupts */ for (;;) { __bis_SR_register(LPM0_bits | GIE); /* Enter LPM0 with interrupts enabled */ __no_operation(); if (g_keyReady) { /* Echo key over UART */ len = sprintf(buf, "Key pressed: %c\r\n", g_lastKey); (void)len; serialPrint(buf); g_keyReady = false; } } /* Should never reach here */ return 0; }