Skip to content

Commit

Permalink
Configure digital pins with SPI
Browse files Browse the repository at this point in the history
  • Loading branch information
mdclyburn committed Jul 10, 2019
1 parent cabaa15 commit 41eace0
Show file tree
Hide file tree
Showing 8 changed files with 140 additions and 43 deletions.
3 changes: 3 additions & 0 deletions src/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ LDFLAGS = -L $(MSP430PATH)/msp430-elf/lib/430 \
objects = \
digital-io.o \
timer.o \
usci.o \
usci-spi.o \
watchdog.o

Expand All @@ -28,6 +29,8 @@ digital-io.o:

timer.o:

usci.o:

usci-spi.o:

watchdog.o:
Expand Down
32 changes: 22 additions & 10 deletions src/digital-io.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ namespace mardev::msp430::digital_io
volatile uint8_t* const port_select_2[] = { registers::P1SEL2, registers::P2SEL2 };
volatile uint8_t* const port_resistor_enable[] = { registers::P1REN, registers::P2REN };



// 0 = pin is not attached to a digital IO port.
const uint8_t pin_port[] = {
0, 1, 1, 1, 1, 1, 1, 2, 2, 2,
Expand Down Expand Up @@ -45,7 +47,8 @@ namespace mardev::msp430::digital_io
};

void set_pin_mode(const uint8_t pin_number,
const pin_mode mode)
const pin_mode mode,
const Function func)
{
const uint8_t port = pin_port[pin_number-1] - 1;
const uint8_t port_mask = pin_port_mask[pin_number-1];
Expand All @@ -64,15 +67,24 @@ namespace mardev::msp430::digital_io
else
*port_resistor_enable[port] &= ~port_mask;

// Select the digital IO function.
*port_select[port] &= ~port_mask;
*port_select_2[port] &= ~port_mask;

// Set output value.
if(mode == pin_mode::input_pullup)
*port_output[port] |= port_mask;
else // Pull-down or set output to low.
*port_output[port] &= ~port_mask;
// Set pin function.
switch(func)
{
case Function::IO: // Select the digital IO function.
*port_select[port] &= ~port_mask;
*port_select_2[port] &= ~port_mask;
break;
case Function::Primary: // Select primary peripheral module function.
*port_select[port] &= ~port_mask;
*port_select_2[port] |= port_mask;
break;
case Function::Special: // Reserved. This is a device-specific setting.
break;
case Function::Secondary: // Select secondary peripheral module function.
*port_select[port] |= port_mask;
*port_select_2[port] |= port_mask;
break;
}

return;
}
Expand Down
21 changes: 18 additions & 3 deletions src/digital-io.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,15 @@ namespace mardev::msp430::digital_io
enum class pin_mode
{
output,
input_pullup,
input_pulldown
input
};

enum class Function : uint8_t
{
IO = 0,
Primary = 1,
Special = 2,
Secondary = 3
};

enum class logic
Expand All @@ -53,9 +60,17 @@ namespace mardev::msp430::digital_io
*
* \param pin_number Pin number.
* \param mode Desired mode.
* \param func Selected module function.
*/
void set_pin_mode(const uint8_t pin_number,
const pin_mode mode);
const pin_mode mode,
const Function func);

inline void set_pin_mode(const uint8_t pin_number,
const pin_mode mode)
{
set_pin_mode(pin_number, mode, Function::IO);
}

/** Read the digital signal on a pin.
*
Expand Down
6 changes: 6 additions & 0 deletions src/interrupt.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@

namespace mardev::msp430::interrupt
{
namespace registers
{
volatile uint8_t* const IE2 = (uint8_t* const) 0x01;
volatile uint8_t* const IFG2 = (uint8_t* const) 0x03;
}

// Digital I/O
const uint16_t* const digital_io_port_1 = (uint16_t* const) 0xFFE4; // P1IFG
const uint16_t* const digital_io_port_2 = (uint16_t* const) 0xFFE6; // P2IFG
Expand Down
51 changes: 46 additions & 5 deletions src/usci-spi.cpp
Original file line number Diff line number Diff line change
@@ -1,8 +1,17 @@
#include "digital-io.h"
#include "interrupt.h"
#include "usci.h"
#include "usci-spi.h"

namespace dio = mardev::msp430::digital_io;
namespace interrupt = mardev::msp430::interrupt;

namespace mardev::msp430::usci::spi
{
const uint8_t SCLK[] = { 6, 7 };
const uint8_t MOSI[] = { 4, 15 };
const uint8_t MISO[] = { 3, 14 };

void initialize(const usci::Module module,
const usci::UCMODE spi_mode,
const UCSSELx clock_source,
Expand All @@ -11,20 +20,52 @@ namespace mardev::msp430::usci::spi
const UCMSB first_bit,
const UC7BIT character_length)
{
volatile uint8_t* const ctl0 = usci::registers::CTL0[(uint8_t)module],
volatile uint8_t* const
ctl0 = usci::registers::CTL0[(uint8_t)module],
* ctl1 = usci::registers::CTL1[(uint8_t)module];

*ctl0 = (uint8_t) clock_phase
*ctl1 |= usci::UCSWRST;

const uint8_t pin_clock = SCLK[(uint8_t) module],
pin_mosi = SCLK[(uint8_t) module],
pin_miso = SCLK[(uint8_t) module];

// Configure pins.
dio::set_pin_mode(pin_clock, dio::pin_mode::output, dio::Function::Secondary);
dio::set_pin_mode(pin_mosi, dio::pin_mode::output, dio::Function::Secondary);
dio::set_pin_mode(pin_miso, dio::pin_mode::input, dio::Function::Secondary);

*ctl1 |= (uint8_t) clock_source;

const uint8_t settings = (uint8_t) clock_phase
| (uint8_t) clock_polarity
| (uint8_t) first_bit
| (uint8_t) character_length
| 1 << 4 // Assume master mode
| (uint8_t) UCMST::Master // Assume master mode
| (uint8_t) spi_mode
| 1; // Synchronous mode enable
*ctl0 = settings;

*ctl1 = (uint8_t) clock_source
| usci::UCSWRST;
*ctl1 &= ~usci::UCSWRST;

return;
}

uint8_t write(const usci::Module module,
const uint8_t data)
{
// Wait for the buffer to be ready.
const uint8_t tx_flag = usci::TXIFG[(uint8_t) module];
while(*interrupt::registers::IFG2 & tx_flag);

// Write data out.
volatile uint8_t* const tx_buffer = usci::registers::TXBUF[(uint8_t) module];
*tx_buffer = data;

// Wait for data to be ready.
const uint8_t rx_flag = usci::RXIFG[(uint8_t) module];
while(*interrupt::registers::IFG2 & rx_flag);
volatile const uint8_t* const rx_buffer = usci::registers::RXBUF[(uint8_t) module];
return *rx_buffer;
}
}
20 changes: 9 additions & 11 deletions src/usci-spi.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ namespace mardev::msp430::usci::spi
enum class UCMST : uint8_t
{
Slave = 0x00,
Master = 0x04
Master = 0x08
};

/** Clock source select */
Expand All @@ -60,23 +60,21 @@ namespace mardev::msp430::usci::spi
SMCLK = 0x80
};

/* initialize()
* optionally set 3- or 4-pin mode?
* set clock phase
* set clock polarity
* set bit direction
* set character length: 7- or 8-bit
* enable synchronous mode (required = 1)
* set clock
* clear the software reset enable bit
*/
// Mapping module -> pin number
extern const uint8_t SCLK[];
extern const uint8_t MOSI[];
extern const uint8_t MISO[];

void initialize(const usci::Module module,
const usci::UCMODE spi_mode,
const UCSSELx clock_source,
const UCCKPH clock_phase,
const UCCKPL clock_polarity,
const UCMSB first_bit,
const UC7BIT character_length);

uint8_t write(const usci::Module,
const uint8_t data);
}

#endif
19 changes: 12 additions & 7 deletions src/usci.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,20 @@ namespace mardev::msp430::usci
{
namespace registers
{
uint8_t* const CTL0[] = { UCA0CTL0, UCB0CTL0 };
uint8_t* const CTL1[] = { UCA0CTL1, UCB0CTL1 };
volatile uint8_t* const CTL0[] = { UCA0CTL0, UCB0CTL0 };
volatile uint8_t* const CTL1[] = { UCA0CTL1, UCB0CTL1 };

uint8_t* const BR0[] = { UCA0BR0, UCB0BR0 };
uint8_t* const BR1[] = { UCA0BR1, UCB0BR1 };
volatile uint8_t* const BR0[] = { UCA0BR0, UCB0BR0 };
volatile uint8_t* const BR1[] = { UCA0BR1, UCB0BR1 };

uint8_t* const STAT[] = { UCA0STAT, UCB0STAT };
volatile uint8_t* const STAT[] = { UCA0STAT, UCB0STAT };

const uint8_t* const RXBUF[] = { UCA0RXBUF, UCB0RXBUF };
uint8_t* const TXBUF[] = { UCA0TXBUF, UCB0TXBUF };
const volatile uint8_t* const RXBUF[] = { UCA0RXBUF, UCB0RXBUF };
volatile uint8_t* const TXBUF[] = { UCA0TXBUF, UCB0TXBUF };
}

const uint8_t RXIE[] = { UCA0RXIE, UCB0RXIE };
const uint8_t TXIE[] = { UCA0TXIE, UCB0TXIE };
const uint8_t RXIFG[] = { UCA0RXIFG, UCB0RXIFG };
const uint8_t TXIFG[] = { UCA0TXIFG, UCB0TXIFG };
}
31 changes: 24 additions & 7 deletions src/usci.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,25 +43,42 @@ namespace mardev::msp430::usci
volatile uint8_t* const UCB0TXBUF = (uint8_t* const) 0x6F;

// ===== Module-Register mapping
extern volatile uint8_t* const CTL0[] = { UCA0CTL0, UCB0CTL0 };
extern volatile uint8_t* const CTL1[] = { UCA0CTL1, UCB0CTL1 };
extern volatile uint8_t* const CTL0[];
extern volatile uint8_t* const CTL1[];

extern volatile uint8_t* const BR0[] = { UCA0BR0, UCB0BR0 };
extern volatile uint8_t* const BR1[] = { UCA0BR1, UCB0BR1 };
extern volatile uint8_t* const BR0[];
extern volatile uint8_t* const BR1[];

extern volatile uint8_t* const STAT[] = { UCA0STAT, UCB0STAT };
extern volatile uint8_t* const STAT[];

extern volatile const uint8_t* const RXBUF[] = { UCA0RXBUF, UCB0RXBUF };
extern volatile uint8_t* const TXBUF[] = { UCA0TXBUF, UCB0TXBUF };
extern volatile const uint8_t* const RXBUF[];
extern volatile uint8_t* const TXBUF[];
}

extern uint8_t const RXIE[];
extern uint8_t const TXIE[];
extern uint8_t const RXIFG[];
extern uint8_t const TXIFG[];

// USCI control register 0 masks
const uint8_t UCMODEx = 0x06;

// USCI control register 1 masks
const uint8_t UCSSELx = 0xC0;
const uint8_t UCSWRST = 0x01;

// Interrupt Enable register masks
const uint8_t UCB0TXIE = 0x08;
const uint8_t UCB0RXIE = 0x04;
const uint8_t UCA0TXIE = 0x02;
const uint8_t UCA0RXIE = 0x01;

// Interrupt Flag 2 register masks
const uint8_t UCB0TXIFG = 0x08;
const uint8_t UCB0RXIFG = 0x04;
const uint8_t UCA0TXIFG = 0x02;
const uint8_t UCA0RXIFG = 0x01;

enum class Module : uint8_t
{
A0 = 0,
Expand Down

0 comments on commit 41eace0

Please sign in to comment.