142 lines
4.3 KiB
C
Executable File
142 lines
4.3 KiB
C
Executable File
/**
|
||
* @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 <msp430.h>
|
||
#include <driverlib.h>
|
||
#include <stdint.h>
|
||
#include <stdio.h>
|
||
#include <stdbool.h>
|
||
#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;
|
||
}
|