Skip to content
Snippets Groups Projects
Commit 7205332a authored by Birte Kristina Friesel's avatar Birte Kristina Friesel
Browse files

add DMX driver for MSP430FR5969 and MSP430FR5994 launchpads

parent 8b5d14c7
No related branches found
No related tags found
No related merge requests found
......@@ -46,6 +46,7 @@ Peripheral communication:
* I²C (master only, interrupt-driven)
* SPI (master only, polling)
* UART (output polling, input interrupt-driven)
* DMX (polling, via UART, overrides regular serial output)
* NeoPixel/WS2812B (Adafruit driver)
Hardware features:
......@@ -56,9 +57,10 @@ Hardware features:
Peripheral communication:
* I²C on eUSCI\_B0 (master only, interrupt-driven)
* SPI on eUSCI\_B0 (master only, polling)
* UART on eUSCI\_A1 (output polling, input interrupt-driven)
* I²C on eUSCI\_B0 (FR5969) / eUSCI\_B1 (FR5994) (master only, interrupt-driven)
* SPI on eUSCI\_B0 (FR5969) / eUSCI\_B1 (FR5994) (master only, polling)
* UART on eUSCI\_A0 (FR5969) / eUSCI\_A1 (FR5994) (output polling, input interrupt-driven)
* DMX on eUSCI\_A1 (FR5969) / eUSCI\_A3 (FR5994) (polling)
Hardware features:
......
/*
* Copyright 2022 Daniel Friesel
*
* SPDX-License-Identifier: BSD-2-Clause
*/
class DMX {
private:
DMX(const DMX &copy);
public:
unsigned char frames[16];
DMX() {}
void setup();
void write();
};
extern DMX dmx;
/*
* Copyright 2022 Daniel Friesel
*
* SPDX-License-Identifier: BSD-2-Clause
*/
class DMX {
private:
DMX(const DMX &copy);
public:
unsigned char frames[16];
DMX() {}
void setup();
void write();
};
extern DMX dmx;
......@@ -23,7 +23,7 @@ void DMX::setup()
#endif
UCSR0B |= _BV(TXEN0);
UCSR0C = _BV(USBS0) | _BV(UCSZ01) | _BV(UCSZ00); // 8 bits
UCSR0C = _BV(USBS0) | _BV(UCSZ01) | _BV(UCSZ00); // MSB first, 8 data bits, 2 stop bits, no parity
}
void DMX::write()
......@@ -31,9 +31,9 @@ void DMX::write()
// Disable UART for reset and mark signals
UCSR0B &= ~_BV(TXEN0);
gpio.output(GPIO::pd1, 0);
arch.delay_us(88); // break
arch.delay_us(88); // break / reset
gpio.output(GPIO::pd1, 1);
arch.delay_us(8);
arch.delay_us(8); // mark
UCSR0B |= _BV(TXEN0); // causes line to go high
for (uint8_t i = 0; i < 16; i++) {
while (!(UCSR0A & _BV(UDRE0)));
......
......@@ -9,6 +9,10 @@ config arch_msp430fr5969lp_driver_counter
bool "Cycle Counter"
select meta_driver_counter
config arch_msp430fr5969lp_driver_dmx
bool "DMX"
select meta_driver_dmx
config arch_msp430fr5969lp_driver_i2c
bool "I2C on eUSCI_B0"
select meta_driver_hardware_i2c
......
......@@ -75,6 +75,10 @@ ifdef CONFIG_arch_msp430fr5969lp_driver_adc
CXX_TARGETS += src/arch/msp430fr5969lp/driver/adc.cc
endif
ifdef CONFIG_arch_msp430fr5969lp_driver_dmx
CXX_TARGETS += src/arch/msp430fr5969lp/driver/dmx.cc
endif
ifdef CONFIG_arch_msp430fr5969lp_driver_stdin
CXX_TARGETS += src/arch/msp430fr5969lp/driver/stdin.cc
endif
......
/*
* Copyright 2022 Daniel Friesel
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <msp430.h>
#include "arch.h"
#include "driver/dmx.h"
#include "driver/gpio.h"
/*
* Baud rate calculation according to datasheet:
* N := f_{BRCLK} / Baudrate = F_CPU / 115200 in our case
* if N <= 16: OS16 = 0, UCBR0 = int(N)
* if N > 16: OS16 = 1, UCBR0 = int(N/16), UCBRF0 = int(((n/16) - int(n/16)) * 16) = int(N)%16
* Set UCBRS0 according to table 21-4
*/
void DMX::setup()
{
UCA1CTLW0 |= UCSWRST;
#if F_CPU == 16000000UL
// 16M / 250000 == 64 -> UCOS16 = 1, UCBR0 = 4, UCBRF0 = 0, UCBRS0 = 0x00
UCA1CTLW0 = UCSWRST | UCSPB | UCSSEL__SMCLK; // MSB first, 8 data bits, 2 stop bits
UCA1MCTLW = UCOS16;
UCA1BR0 = 4;
#else
#error Unsupported F_CPU
#endif
UCA1IRCTL = 0;
UCA1ABCTL = 0;
P2SEL0 &= ~BIT5;
P2SEL1 |= BIT5;
P2DIR |= BIT5;
UCA1CTLW0 &= ~UCSWRST;
}
void DMX::write()
{
// Disable UART for reset and mark signals
UCA1CTLW0 |= UCSWRST;
P2SEL1 &= ~BIT5;
gpio.output(GPIO::p2_5, 0);
arch.delay_us(88); // break / reset
gpio.output(GPIO::p2_5, 1);
arch.delay_us(8); // mark
P2SEL1 |= BIT5;
UCA1CTLW0 &= ~UCSWRST; // causes line to go high
for (unsigned char i = 0; i < 16; i++) {
while (!(UCA1IFG & UCTXIFG));
UCA1TXBUF = frames[i];
}
for (unsigned char i = 0; i < 241; i++) {
while (!(UCA1IFG & UCTXIFG));
UCA1TXBUF = 0;
}
for (unsigned char i = 0; i < 255; i++) {
while (!(UCA1IFG & UCTXIFG));
UCA1TXBUF = 0;
}
}
DMX dmx;
......@@ -9,6 +9,10 @@ config arch_msp430fr5994lp_driver_counter
bool "Cycle Counter"
select meta_driver_counter
config arch_msp430fr5994lp_driver_dmx
bool "DMX"
select meta_driver_dmx
config arch_msp430fr5994lp_driver_i2c
bool "I2C on eUSCI_B1"
select meta_driver_hardware_i2c
......
......@@ -90,6 +90,10 @@ ifdef CONFIG_arch_msp430fr5994lp_driver_adc
CXX_TARGETS += src/arch/msp430fr5994lp/driver/adc.cc
endif
ifdef CONFIG_arch_msp430fr5994lp_driver_dmx
CXX_TARGETS += src/arch/msp430fr5994lp/driver/dmx.cc
endif
ifdef CONFIG_arch_msp430fr5994lp_driver_stdin
CXX_TARGETS += src/arch/msp430fr5994lp/driver/stdin.cc
endif
......
/*
* Copyright 2022 Daniel Friesel
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <msp430.h>
#include "arch.h"
#include "driver/dmx.h"
#include "driver/gpio.h"
/*
* Baud rate calculation according to datasheet:
* N := f_{BRCLK} / Baudrate = F_CPU / 115200 in our case
* if N <= 16: OS16 = 0, UCBR0 = int(N)
* if N > 16: OS16 = 1, UCBR0 = int(N/16), UCBRF0 = int(((n/16) - int(n/16)) * 16) = int(N)%16
* Set UCBRS0 according to table 21-4
*/
void DMX::setup()
{
UCA3CTLW0 |= UCSWRST;
#if F_CPU == 16000000UL
// 16M / 250000 == 64 -> UCOS16 = 1, UCBR0 = 4, UCBRF0 = 0, UCBRS0 = 0x00
UCA3CTLW0 = UCSWRST | UCSPB | UCSSEL__SMCLK; // MSB first, 8 data bits, 2 stop bits
UCA3MCTLW = UCOS16;
UCA3BR0 = 4;
#else
#error Unsupported F_CPU
#endif
UCA3IRCTL = 0;
UCA3ABCTL = 0;
P6SEL0 |= BIT0;
P6SEL1 &= ~BIT0;
P6DIR |= BIT0;
UCA3CTLW0 &= ~UCSWRST;
}
void DMX::write()
{
// Disable UART for reset and mark signals
UCA3CTLW0 |= UCSWRST;
P6SEL0 &= ~BIT0;
gpio.output(GPIO::p2_5, 0);
arch.delay_us(88); // break / reset
gpio.output(GPIO::p2_5, 1);
arch.delay_us(8); // mark
P6SEL0 |= BIT0;
UCA3CTLW0 &= ~UCSWRST; // causes line to go high
for (unsigned char i = 0; i < 16; i++) {
while (!(UCA3IFG & UCTXIFG));
UCA3TXBUF = frames[i];
}
for (unsigned char i = 0; i < 241; i++) {
while (!(UCA3IFG & UCTXIFG));
UCA3TXBUF = 0;
}
for (unsigned char i = 0; i < 255; i++) {
while (!(UCA3IFG & UCTXIFG));
UCA3TXBUF = 0;
}
}
DMX dmx;
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment