feat: LCD working!

This commit is contained in:
Frederik Beimgraben 2025-07-03 00:26:05 +02:00
parent 362251773d
commit 34a965f03a
20 changed files with 212 additions and 194 deletions

View File

@ -8,5 +8,7 @@ encoding//Debug/latex/subdir_vars.mk=UTF-8
encoding//Debug/makefile=UTF-8
encoding//Debug/objects.mk=UTF-8
encoding//Debug/sources.mk=UTF-8
encoding//Debug/src/subdir_rules.mk=UTF-8
encoding//Debug/src/subdir_vars.mk=UTF-8
encoding//Debug/subdir_rules.mk=UTF-8
encoding//Debug/subdir_vars.mk=UTF-8

View File

@ -119,11 +119,6 @@
"command" : "clang++ -I\"/home/frederik/.ti/ccs2010/ccs/ccs_base/msp430/include\" -I\"/home/frederik/workspace_ccstheia/ESR-11\" -I\"/home/frederik/workspace_ccstheia/ESR-11/jsmn\" -I\"/home/frederik/workspace_ccstheia/ESR-11/driverlib/MSP430FR2xx_4xx\" -I\"/home/frederik/.ti/ccs2010/ccs/tools/compiler/ti-cgt-msp430_21.6.1.LTS/include\" -D__MSP430FR2355__ -D_FRWP_ENABLE -D_INFO_FRWP_ENABLE -xc",
"file" : "/home/frederik/workspace_ccstheia/ESR-11/jsmn/jsmn.c"
},
{
"directory" : "/home/frederik/workspace_ccstheia/ESR-11/Debug",
"command" : "clang++ -I\"/home/frederik/.ti/ccs2010/ccs/ccs_base/msp430/include\" -I\"/home/frederik/workspace_ccstheia/ESR-11\" -I\"/home/frederik/workspace_ccstheia/ESR-11/jsmn\" -I\"/home/frederik/workspace_ccstheia/ESR-11/driverlib/MSP430FR2xx_4xx\" -I\"/home/frederik/.ti/ccs2010/ccs/tools/compiler/ti-cgt-msp430_21.6.1.LTS/include\" -D__MSP430FR2355__ -D_FRWP_ENABLE -D_INFO_FRWP_ENABLE -xc",
"file" : "/home/frederik/workspace_ccstheia/ESR-11/keypad.c"
},
{
"directory" : "/home/frederik/workspace_ccstheia/ESR-11/Debug",
"command" : "clang++ -I\"/home/frederik/.ti/ccs2010/ccs/ccs_base/msp430/include\" -I\"/home/frederik/workspace_ccstheia/ESR-11\" -I\"/home/frederik/workspace_ccstheia/ESR-11/jsmn\" -I\"/home/frederik/workspace_ccstheia/ESR-11/driverlib/MSP430FR2xx_4xx\" -I\"/home/frederik/.ti/ccs2010/ccs/tools/compiler/ti-cgt-msp430_21.6.1.LTS/include\" -D__MSP430FR2355__ -D_FRWP_ENABLE -D_INFO_FRWP_ENABLE -xc",
@ -132,16 +127,26 @@
{
"directory" : "/home/frederik/workspace_ccstheia/ESR-11/Debug",
"command" : "clang++ -I\"/home/frederik/.ti/ccs2010/ccs/ccs_base/msp430/include\" -I\"/home/frederik/workspace_ccstheia/ESR-11\" -I\"/home/frederik/workspace_ccstheia/ESR-11/jsmn\" -I\"/home/frederik/workspace_ccstheia/ESR-11/driverlib/MSP430FR2xx_4xx\" -I\"/home/frederik/.ti/ccs2010/ccs/tools/compiler/ti-cgt-msp430_21.6.1.LTS/include\" -D__MSP430FR2355__ -D_FRWP_ENABLE -D_INFO_FRWP_ENABLE -xc",
"file" : "/home/frederik/workspace_ccstheia/ESR-11/morse.c"
"file" : "/home/frederik/workspace_ccstheia/ESR-11/src/i2c.c"
},
{
"directory" : "/home/frederik/workspace_ccstheia/ESR-11/Debug",
"command" : "clang++ -I\"/home/frederik/.ti/ccs2010/ccs/ccs_base/msp430/include\" -I\"/home/frederik/workspace_ccstheia/ESR-11\" -I\"/home/frederik/workspace_ccstheia/ESR-11/jsmn\" -I\"/home/frederik/workspace_ccstheia/ESR-11/driverlib/MSP430FR2xx_4xx\" -I\"/home/frederik/.ti/ccs2010/ccs/tools/compiler/ti-cgt-msp430_21.6.1.LTS/include\" -D__MSP430FR2355__ -D_FRWP_ENABLE -D_INFO_FRWP_ENABLE -xc",
"file" : "/home/frederik/workspace_ccstheia/ESR-11/i2c.c"
"file" : "/home/frederik/workspace_ccstheia/ESR-11/src/keypad.c"
},
{
"directory" : "/home/frederik/workspace_ccstheia/ESR-11/Debug",
"command" : "clang++ -I\"/home/frederik/.ti/ccs2010/ccs/ccs_base/msp430/include\" -I\"/home/frederik/workspace_ccstheia/ESR-11\" -I\"/home/frederik/workspace_ccstheia/ESR-11/jsmn\" -I\"/home/frederik/workspace_ccstheia/ESR-11/driverlib/MSP430FR2xx_4xx\" -I\"/home/frederik/.ti/ccs2010/ccs/tools/compiler/ti-cgt-msp430_21.6.1.LTS/include\" -D__MSP430FR2355__ -D_FRWP_ENABLE -D_INFO_FRWP_ENABLE -xc",
"file" : "/home/frederik/workspace_ccstheia/ESR-11/lcd.c"
"file" : "/home/frederik/workspace_ccstheia/ESR-11/src/lcd.c"
},
{
"directory" : "/home/frederik/workspace_ccstheia/ESR-11/Debug",
"command" : "clang++ -I\"/home/frederik/.ti/ccs2010/ccs/ccs_base/msp430/include\" -I\"/home/frederik/workspace_ccstheia/ESR-11\" -I\"/home/frederik/workspace_ccstheia/ESR-11/jsmn\" -I\"/home/frederik/workspace_ccstheia/ESR-11/driverlib/MSP430FR2xx_4xx\" -I\"/home/frederik/.ti/ccs2010/ccs/tools/compiler/ti-cgt-msp430_21.6.1.LTS/include\" -D__MSP430FR2355__ -D_FRWP_ENABLE -D_INFO_FRWP_ENABLE -xc",
"file" : "/home/frederik/workspace_ccstheia/ESR-11/src/morse.c"
},
{
"directory" : "/home/frederik/workspace_ccstheia/ESR-11/Debug",
"command" : "clang++ -I\"/home/frederik/.ti/ccs2010/ccs/ccs_base/msp430/include\" -I\"/home/frederik/workspace_ccstheia/ESR-11\" -I\"/home/frederik/workspace_ccstheia/ESR-11/jsmn\" -I\"/home/frederik/workspace_ccstheia/ESR-11/driverlib/MSP430FR2xx_4xx\" -I\"/home/frederik/.ti/ccs2010/ccs/tools/compiler/ti-cgt-msp430_21.6.1.LTS/include\" -D__MSP430FR2355__ -D_FRWP_ENABLE -D_INFO_FRWP_ENABLE -xc",
"file" : "/home/frederik/workspace_ccstheia/ESR-11/src/state_machine.c"
}
]

View File

@ -1,18 +0,0 @@
/* ========================================================================== */
/* constants.h */
/* ========================================================================== */
/**
* @file constants.h
* @brief Projektweite Konstanten
* @author Frederik Beimgraben
* @author Minh Dan Cam
* @author Luis Meyer
* @date 02.07.2025
*/
#ifndef CONSTANTS_H
#define CONSTANTS_H
#define NULL 0
#endif /* CONSTANTS_H */

44
i2c.h
View File

@ -1,44 +0,0 @@
/* ========================================================================== */
/* I2C.h */
/* ========================================================================== */
/**
* @file I2C.h
* @author wehrberger
* @date 31.05.2025
*
* @brief Schnittstelle für einen minimalen blockierenden I²C-Master-Treiber.
*/
#ifndef I2C_H
#define I2C_H
#include <stdint.h>
#include <stdbool.h>
/**
* @brief Initialisiert das I²C-Modul als Master (SMCLK/20 50 kHz).
*/
void I2C_init(void);
/**
* @brief Sendet ein Datenpacket an einen I²C-Slave.
*
* @param slaveAddress 7-Bit I²C-Adresse des Zielgeräts.
* @param data Zeiger auf zu sendende Bytes.
* @param length Anzahl der zu sendenden Bytes.
*/
void I2C_write(uint8_t slaveAddress, char data[], uint8_t length);
/**
* @brief Liest ein einzelnes Byte aus einem Register eines I²C-Slaves.
*
* Führt zunächst einen Schreibvorgang durch, um die Registeradresse zu senden,
* und liest dann per Repeated START ein Byte zurück.
*
* @param slaveAddress 7-Bit I²C-Adresse des Zielgeräts.
* @param registerAddress Adresse des auszulesenden Registers.
* @return Das gelesene Byte.
*/
char I2C_read_reg(uint8_t slaveAddress, uint8_t registerAddress);
#endif /* I2C_H */

View File

@ -1,20 +0,0 @@
/**
* @file keypad.h
* @brief Simple interrupt-driven 4×4 keypad driver.
*/
#ifndef KEYPAD_H
#define KEYPAD_H
#include <stdint.h>
/** Signature of the callback invoked on a confirmed key press */
typedef void (*KeypadCallback_t)(char key);
/**
* @brief Initialize the keypad pins & interrupts.
* @param cb Function to call when a key is pressed.
*/
void initKeypadInterrupts(KeypadCallback_t cb);
#endif // KEYPAD_H

View File

@ -1,56 +0,0 @@
--- keypad.c.orig 2025-07-01 12:00:00.000000000 +0000
+++ keypad.c 2025-07-01 12:05:00.000000000 +0000
@@ /* P1/P2 share PORT1_VECTOR */
#pragma vector=PORT1_VECTOR
__interrupt void PORT1_ISR(void)
{
uint16_t status = GPIO_getInterruptStatus(GPIO_PORT_P2, colPin[COL3]);
if (status & colPin[COL3]) {
- handleColumnInterrupt(COL3);
- GPIO_clearInterrupt(GPIO_PORT_P2, colPin[COL3]);
+ handleColumnInterrupt(COL3);
+ /* wake main out of LPM0 */
+ __bic_SR_register_on_exit(LPM0_bits);
+ GPIO_clearInterrupt(GPIO_PORT_P2, colPin[COL3]);
}
}
@@ /** P3/P4 share PORT3_VECTOR **/
-#pragma vector=PORT3_VECTOR
+/* P3/P4 share the *second* port vector on FR2 devices */
+#pragma vector=PORT2_VECTOR
__interrupt void PORT3_ISR(void)
{
uint16_t status = GPIO_getInterruptStatus(GPIO_PORT_P3, colPin[COL2]);
if (status & colPin[COL2]) {
- handleColumnInterrupt(COL2);
- GPIO_clearInterrupt(GPIO_PORT_P3, colPin[COL2]);
+ handleColumnInterrupt(COL2);
+ /* wake main out of LPM0 */
+ __bic_SR_register_on_exit(LPM0_bits);
+ GPIO_clearInterrupt(GPIO_PORT_P3, colPin[COL2]);
}
}
@@ /** P5/P6 share PORT5_VECTOR **/
-#pragma vector=PORT5_VECTOR
+/* P5/P6 share the *third* port vector on FR2 devices */
+#pragma vector=PORT3_VECTOR
__interrupt void PORT5_ISR(void)
{
uint16_t mask = colPin[COL0] | colPin[COL1];
uint16_t status = GPIO_getInterruptStatus(GPIO_PORT_P6, mask);
if (status & colPin[COL0]) {
- handleColumnInterrupt(COL0);
+ handleColumnInterrupt(COL0);
+ /* wake main out of LPM0 */
+ __bic_SR_register_on_exit(LPM0_bits);
}
if (status & colPin[COL1]) {
- handleColumnInterrupt(COL1);
+ handleColumnInterrupt(COL1);
+ /* wake main out of LPM0 */
+ __bic_SR_register_on_exit(LPM0_bits);
}
GPIO_clearInterrupt(GPIO_PORT_P6, mask);
}

35
lcd.h
View File

@ -1,35 +0,0 @@
#ifndef LCD_I2C_H
#define LCD_I2C_H
#include <stdint.h>
/* PCF8574 I²C-Expander Adresse */
#define LCD_I2C_ADDR 0x27
/* PCF8574 P-Pins → LCD Control */
#define LCD_BACKLIGHT 0x08
#define LCD_ENABLE 0x04
#define LCD_RW 0x02
#define LCD_RS 0x01
/**
* @brief Initialisiert das LCD (4-Bit-Modus, 2 Zeilen, 5×8 Punkte).
*/
void lcd_init(void);
/**
* @brief Löscht das Display und setzt Cursor auf Home.
*/
void lcd_clear(void);
/**
* @brief Setzt den Cursor auf (row, col). Zero-based: row=0..1, col=0..15.
*/
void lcd_set_cursor(uint8_t row, uint8_t col);
/**
* @brief Schreibt einen C-String ins Display an der aktuellen Cursor-Position.
*/
void lcd_print(const char *str);
#endif /* LCD_I2C_H */

30
main.c
View File

@ -13,15 +13,19 @@
#include <stdint.h>
#include <stdio.h>
#include <stdbool.h>
#include "keypad.h"
#include "morse.h"
#include "i2c.h"
#include "Board.h"
#include "src/keypad.h"
#include "src/morse.h"
#include "src/i2c.h"
#include "src/lcd.h"
#include "src/Board.h"
/** 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 */
volatile char last_key_pressed = '\0';
volatile bool key_changed = false;
/**
* @brief Keypad callback invoked on key press interrupt.
* @param key ASCII character of pressed key
@ -30,7 +34,8 @@
*/
static void myKeyHandler(char key)
{
blinkMorseChar(key);
last_key_pressed = key;
key_changed = true;
}
void init_timer(void) {
@ -106,17 +111,22 @@ int main(void)
lcd_init(); /* LCD initialisieren */
lcd_set_cursor(0, 0);
lcd_print("Hello, world!");
lcd_set_cursor(1, 0);
lcd_print("MSP430 + I2C");
lcd_print("Press any Key!");
/* Enter low-power mode and wait for key interrupts */
for (;;) {
__bis_SR_register(LPM0_bits | GIE); /* Enter LPM0 with interrupts enabled */
__no_operation();
/* Do nothing */
if (key_changed) {
lcd_set_cursor(1, 0);
char output[20] = "Key pressed: ";
output[13] = last_key_pressed;
lcd_print(output);
key_changed = false;
}
}
}

19
src/constants.h Normal file
View File

@ -0,0 +1,19 @@
/* File: constants.h */
/**
* @file constants.h
* @brief Common constants missing from standard headers (C90).
*
* @author
* Frederik Beimgraben
* Minh Dan Cam
* Luis Meyer
* @date 2025-07-02
*/
#ifndef CONSTANTS_H
#define CONSTANTS_H
/** @brief Null pointer constant for C90. */
#define NULL 0
#endif /* CONSTANTS_H */

View File

@ -35,7 +35,7 @@ void I2C_init(void)
// SMCLK wählen und durch 20 teilen → 50 kHz SCL
UCB0CTLW0 |= UCSSEL_3;
UCB0BRW = 20;
UCB0BRW = 50;
// I²C Master, 7-Bit Adressierung
UCB0CTLW0 |= UCMODE_3 | UCMST;

42
src/i2c.h Normal file
View File

@ -0,0 +1,42 @@
/* File: i2c.h */
/**
* @file i2c.h
* @brief Interface for a minimal blocking I²C master driver (MSP430FR2355).
*
* Provides initialization, blocking write, and single-byte register read.
*
* @author
* Frederik Beimgraben
* Minh Dan Cam
* Luis Meyer
* @date 2025-07-02
*/
#ifndef I2C_H
#define I2C_H
#include <stdint.h>
#include <stdbool.h>
/**
* @brief Initialize the I2C module as master (SMCLK/20 50 kHz SCL).
*/
void I2C_init(void);
/**
* @brief Send a data packet to an I2C slave.
* @param slaveAddress 7-bit address of the target device.
* @param data Pointer to the data buffer to send.
* @param length Number of bytes to send.
*/
void I2C_write(uint8_t slaveAddress, char data[], uint8_t length);
/**
* @brief Read a single byte from a specific register of an I2C slave.
* @param slaveAddress 7-bit address of the target device.
* @param registerAddress Register address to read.
* @return The byte read from the device.
*/
char I2C_read_reg(uint8_t slaveAddress, uint8_t registerAddress);
#endif /* I2C_H */

View File

@ -44,7 +44,7 @@ static const uint16_t rowPin [ROWS] = { GPIO_PIN0, GPIO_PIN1, GPIO_PIN2, GPIO_PI
/** Column port and pin definitions */
enum { COL0 = 0, COL1, COL2, COL3 };
static const uint8_t colPort[COLS] = { GPIO_PORT_P3, GPIO_PORT_P1, GPIO_PORT_P3, GPIO_PORT_P1 };
static const uint16_t colPin [COLS] = { GPIO_PIN0, GPIO_PIN1, GPIO_PIN2, GPIO_PIN4 };
static const uint16_t colPin [COLS] = { GPIO_PIN0, GPIO_PIN4, GPIO_PIN2, GPIO_PIN1 };
/** User callback invoked on confirmed key press */
static KeypadCallback_t keyCallback = NULL;
@ -140,7 +140,7 @@ __interrupt void PORT1_ISR(void)
handleColumnInterrupt(COL1);
__bic_SR_register_on_exit(LPM0_bits);
}
if (status & colPin[COL3]) {
handleColumnInterrupt(COL3);
__bic_SR_register_on_exit(LPM0_bits);

32
src/keypad.h Normal file
View File

@ -0,0 +1,32 @@
/* File: keypad.h */
/**
* @file keypad.h
* @brief API for 4×4 matrix keypad driver (MSP430FR2355).
*
* Interrupt-driven scanning with callback on key press.
*
* @authors
* Frederik Beimgraben
* Minh Dan Cam
* Luis Meyer
* @date 2025-07-02
*/
#ifndef KEYPAD_H
#define KEYPAD_H
#include <stdint.h>
/**
* @brief Callback invoked on a confirmed key press.
* @param key ASCII character of the pressed key.
*/
typedef void (*KeypadCallback_t)(char key);
/**
* @brief Initialize the keypad pins and interrupts.
* @param cb User callback for key events.
*/
void initKeypadInterrupts(KeypadCallback_t cb);
#endif /* KEYPAD_H */

View File

51
src/lcd.h Normal file
View File

@ -0,0 +1,51 @@
/* File: lcd.h */
/**
* @file lcd.h
* @brief API for 1602A-LCD via PCF8574 I²C backpack (0x27) in 4-bit mode.
*
* Uses blocking I2C transfers via I2C_write().
*
* @authors
* Frederik Beimgraben
* Minh Dan Cam
* Luis Meyer
* @date 2025-07-02
*/
#ifndef LCD_I2C_H
#define LCD_I2C_H
#include <stdint.h>
/** I2C address of the PCF8574 backpack. */
#define LCD_I2C_ADDR 0x27u
/** PCF8574 → LCD control bits. */
#define LCD_BACKLIGHT 0x08u
#define LCD_ENABLE 0x04u
#define LCD_RW 0x02u
#define LCD_RS 0x01u
/**
* @brief Initialize the LCD (4-bit, 2 lines, 5×8 dots).
*/
void lcd_init(void);
/**
* @brief Clear the display and return cursor to home position.
*/
void lcd_clear(void);
/**
* @brief Set cursor position.
* @param row Zero-based row index (01).
* @param col Zero-based column index (015).
*/
void lcd_set_cursor(uint8_t row, uint8_t col);
/**
* @brief Write a null-terminated string at current cursor position.
* @param str ASCII string to display.
*/
void lcd_print(const char *str);
#endif /* LCD_I2C_H */

15
src/state_machine.c Normal file
View File

@ -0,0 +1,15 @@
/* File: state_machine.c */
/**
* @file state_machine.c
* @brief Statemachine for the Core-Program
*
* ...
*
* @authors
* Frederik Beimgraben
* Minh Dan Cam
* Luis Meyer
* @date 2025-07-02
*/

15
src/state_machine.h Normal file
View File

@ -0,0 +1,15 @@
/* File: state_machine.h */
/**
* @file state_machine.h
* @brief Statemachine for the Core-Program
*
* ...
*
* @authors
* Frederik Beimgraben
* Minh Dan Cam
* Luis Meyer
* @date 2025-07-02
*/
static void keypad_handler(char key);