Jump to content
43oh

USI, USCI_B driver for SPI LED (Oasis)


Recommended Posts

Wrote a quick driver and a handful of print functions for displaying data on one of the Oasis SPI LED displays from this thread-- http://forum.43oh.co...gment-displays/

 

You'll notice some crap about #ifdef _MSPRF24_H_ ... that's so that I can reuse my SPI drivers from my nRF24L01+ library with just a minor modification (spi_mode_2() reconfigures them for this chip, spi_mode_0() reconfigures it back for the nRF24L01+)

 

Also, the various functions take a pointer to the SFR that your STBY line is connected to along with an unsigned 8-bit integer representing the port bit.

 

E.g.:

oasisdisp_init(&P1OUT, BIT1); // STBY connected to P1.1

 

Header file - oasisdisp.h


/* oasisdisp.h
*
* Oasis SPI LED driver library
*/

#ifndef _OASISDISP_H_
#define _OASISDISP_H_

#include <stdint.h>

void spi_mode_2();
void spi_mode_0();

#ifndef _MSPRF24_H_
void spi_init();
uint8_t spi_transfer(uint8_t inb);
#endif

/* The volatile unsigned char * plus unsigned char passed includes the SFR for the Port attached
* to the STBY (SPI Chip Select) line of the target display. Pass this along to each call.
*
* Note that in order to talk to this display after we've been talking to other SPI devices, it may
* be necessary to wrap these calls in spi_mode_2() and run spi_mode_0() at the end to reconfigure
* for whichever other devices we have (e.g. nRF24L01+).
*/

void oasisdisp_init(volatile unsigned char *, unsigned char, uint8_t brightness); // Brightness: 0-7
void oasisdisp_write_digit(volatile unsigned char *, unsigned char, uint8_t, uint8_t);
void oasisdisp_write_space(volatile unsigned char *, unsigned char, uint8_t);
void oasisdisp_write_dash(volatile unsigned char *, unsigned char, uint8_t);

void oasisdisp_print_uint(volatile unsigned char *, unsigned char, unsigned int);
void oasisdisp_print_int(volatile unsigned char *, unsigned char, int);

void oasisdisp_print_byte(volatile unsigned char *, unsigned char, uint8_t); // Hex dump of a single byte
void oasisdisp_print_word(volatile unsigned char *, unsigned char, uint16_t); // Hex dump of two bytes

#endif

 

Library file - oasisdisp.c


/* oasisdisp.c
*
* Driver for Oasis 4-digit 7-segment LED display
*/

#include <msp430.h>
#include "oasisdisp.h"
#include <stdint.h>

const char oasisdisp_DIGITS[16] = {0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f, 0x77, 0x7c, 0x58, 0x5e, 0x79, 0x71};

void spi_mode_2()
{
#ifdef __MSP430_HAS_USI__
   USICTL0 |= USILSB;
   USICTL1 &= ~USICKPH;
   USICKCTL |= USICKPL;
#endif

#ifdef __MSP430_HAS_USCI__
   UCB0CTL0 &= ~(UCCKPH | UCMSB);
   UCB0CTL0 |= UCCKPL;
#endif
}

void spi_mode_0()
{
#ifdef __MSP430_HAS_USI__
   USICTL0 &= ~USILSB;
   USICTL1 |= USICKPH;
   USICKCTL &= ~USICKPL;
#endif

#ifdef __MSP430_HAS_USCI__
   UCB0CTL0 |= UCCKPH | UCMSB;
   UCB0CTL0 &= ~UCCKPL;
#endif

}

// Wrapping this because we don't need this if we are using the msprf24 nRF24L01+ library...
#ifndef _MSPRF24_H_

// USI
#ifdef __MSP430_HAS_USI__
void spi_init()
{
   /* USI SPI setup */
   USICTL0 |= USISWRST;
   USICTL1 = 0;
   USICKCTL = USICKPL | USISSEL_2 | USIDIV_3;  // Clock source = SMCLK/1
   USICTL0 = USIPE7 | USIPE6 | USIPE5 | USIMST | USILSB | USIOE;
   USISR = 0x0000;
}

uint8_t spi_transfer(uint8_t inb)
{
   USISRL = inb;
   USICNT = 8;            // Start SPI transfer
   while ( !(USICTL1 & USIIFG) )
       ;
   USICTL1 &= ~USIIFG;
   return USISRL;
}
#endif

// USCI_B
#ifdef __MSP430_HAS_USCI__
void spi_init()
{
   /* Configure ports on MSP430 device for USCI_B */
   P1SEL |= BIT5 | BIT6 | BIT7;
   P1SEL2 |= BIT5 | BIT6 | BIT7;

   /* USCI-B specific SPI setup */

   UCB0CTL1 |= UCSWRST;
   UCB0CTL0 = UCCKPL | UCMST | UCMODE_0 | UCSYNC;  // SPI mode 0, master
   UCB0BR0 = 0x01;  // SPI clocked at same speed as SMCLK
   UCB0BR1 = 0x00;
   UCB0CTL1 = UCSSEL_2;  // Clock = SMCLK, clear UCSWRST and enables USCI_B module.
}
uint8_t spi_transfer(uint8_t inb)
{
   UCB0TXBUF = inb;
   while ( !(IFG2 & UCB0RXIFG) )  // Wait for RXIFG indicating remote byte received via SOMI
       ;
   return UCB0RXBUF;
}
#endif
//

#endif

void oasisdisp_init(volatile unsigned char *portout, unsigned char bit, uint8_t brightness)
{
   *portout &= ~bit;
   spi_transfer(0x02);
   *portout |= bit;
   *portout &= ~bit;
   spi_transfer(0x40);
   *portout |= bit;
   *portout &= ~bit;
   spi_transfer(0x88 | (brightness & 0x07));
   *portout |= bit;
}

void oasisdisp_write_digit(volatile unsigned char *portout, unsigned char bit, uint8_t digit, uint8_t numeral)
{
   if (digit > 3)
       return;
   *portout &= ~bit;
   spi_transfer(0xC0 + digit*2);

   spi_transfer(oasisdisp_DIGITS[numeral & 0x0F]);
   *portout |= bit;
}

void oasisdisp_write_space(volatile unsigned char *portout, unsigned char bit, uint8_t digit)
{
   if (digit > 3)
       return;
   *portout &= ~bit;
   spi_transfer(0xC0 + digit*2);
   spi_transfer(0x00);
   *portout |= bit;
}

void oasisdisp_write_dash(volatile unsigned char *portout, unsigned char bit, uint8_t digit)
{
   if (digit > 3)
       return;
   *portout &= ~bit;
   spi_transfer(0xC0 + digit*2);
   spi_transfer(0x40);
   *portout |= bit;
}

void oasisdisp_print_uint(volatile unsigned char *portout, unsigned char bit, unsigned int num)
{
   uint8_t force_zero = 0;

   if (num >= 10000) {  // Only 4 digits here, can't display it...
       num -= (num/10000)*10000;
       force_zero = 1;
   }
   if (num >= 1000 || force_zero) {
       oasisdisp_write_digit(portout, bit, 0, num/1000);
       num -= (num/1000)*1000;
       force_zero = 1;
   } else {

       oasisdisp_write_space(portout, bit, 0);
   }
   if (num >= 100 || force_zero) {
       oasisdisp_write_digit(portout, bit, 1, num/100);
       num -= (num/100)*100;
       force_zero = 1;
   } else {
       oasisdisp_write_space(portout, bit, 1);
   }
   if (num >= 10 || force_zero) {
       oasisdisp_write_digit(portout, bit, 2, num/10);
       num -= (num/10)*10;
       force_zero = 1;
   } else {
       oasisdisp_write_space(portout, bit, 2);
   }
   oasisdisp_write_digit(portout, bit, 3, num);
}

void oasisdisp_print_int(volatile unsigned char *portout, unsigned char bit, int num)
{
   uint8_t i, force_zero = 0, negative = 0;

   if (num < 0) {
       // Temporarily using 'negative' to store the digit index for the negative sign
       num = -num;
       if (num >= 100)
           negative = 0;
       else if (num >= 10)
           negative = 1;
       else
           negative = 2;
       oasisdisp_write_dash(portout, bit, negative);
       for (i = 0; i < negative; i++)
           oasisdisp_write_space(portout, bit, i);

       if (num >= 10000) {

           num -= (num/10000)*10000;
           force_zero = 1;
       }
       if (num >= 1000) {
           num -= (num/1000)*1000;
           force_zero = 1;
       }
       negative = 1;
   }
   if (num >= 10000) {  // Only 4 digits here, can't display it...
       num -= (num/10000)*10000;
       force_zero = 1;
   }
   if (!negative && (num >= 1000 || force_zero)) {
       oasisdisp_write_digit(portout, bit, 0, num/1000);
       num -= (num/1000)*1000;
       force_zero = 1;
   } else {
       if (!negative)
           oasisdisp_write_space(portout, bit, 0);
   }
   if (num >= 100 || force_zero) {
       oasisdisp_write_digit(portout, bit, 1, num/100);
       num -= (num/100)*100;
       force_zero = 1;
   } else {
       if (!negative)
           oasisdisp_write_space(portout, bit, 1);
   }
   if (num >= 10 || force_zero) {
       oasisdisp_write_digit(portout, bit, 2, num/10);
       num -= (num/10)*10;
       force_zero = 1;
   } else {
       if (!negative)
           oasisdisp_write_space(portout, bit, 2);
   }

   oasisdisp_write_digit(portout, bit, 3, num);
}

void oasisdisp_print_byte(volatile unsigned char *portout, unsigned char bit, uint8_t 
{
   oasisdisp_write_space(portout, bit, 0);
   oasisdisp_write_space(portout, bit, 1);
   oasisdisp_write_digit(portout, bit, 2, (b >> 4) & 0x0F);
   oasisdisp_write_digit(portout, bit, 3, b & 0x0F);
}

void oasisdisp_print_word(volatile unsigned char *portout, unsigned char bit, uint16_t 
{
   oasisdisp_write_digit(portout, bit, 0, (b >> 12) & 0x0F);
   oasisdisp_write_digit(portout, bit, 1, (b >> 8) & 0x0F);
   oasisdisp_write_digit(portout, bit, 2, (b >> 4) & 0x0F);
   oasisdisp_write_digit(portout, bit, 3, b & 0x0F);
}

Link to post
Share on other sites

Example program, just displays four 9's:

 


/* Four-Nines
* Connect to an Oasis SPI LED display and display four 9's
*/

#include <msp430.h>
#include <stdint.h>
#include "oasisdisp.h"

int main()
{
   WDTCTL = WDTPW | WDTHOLD;
   DCOCTL = CALDCO_16MHZ;
   BCSCTL1 = CALBC1_16MHZ;
   BCSCTL2 = DIVS_2; // SMCLK = 8MHz

   P1DIR |= BIT1;
   P1OUT |= BIT1;
   P1SEL &= ~BIT1;
   P1SEL2 &= ~BIT1;

   spi_init();
   spi_mode_2();
   spi_transfer(0x00); // Strawman xfer to cover G2452 errata USI5

   oasisdisp_init(&P1OUT, BIT1, 7);

   oasisdisp_print_int(&P1OUT, BIT1, 9999);

   LPM4;
   return 0;
}

Link to post
Share on other sites

Another example, printing a hex word to the display (a pointer):

 


/* Pointer-Lib
* Connect to an Oasis SPI LED display and display the hex pointer address for a variable
*/

#include <msp430.h>
#include <stdint.h>
#include "oasisdisp.h"

int main()
{
   uint8_t biznatch;

   WDTCTL = WDTPW | WDTHOLD;
   DCOCTL = CALDCO_16MHZ;
   BCSCTL1 = CALBC1_16MHZ;
   BCSCTL2 = DIVS_2;  // SMCLK = 8MHz
   BCSCTL3 = LFXT1S_2;  // ACLK = VLO
   __delay_cycles(8000);     // Wait for VLO settling
   while (BCSCTL3 & LFXT1OF)
       ;

   P1DIR |= BIT1;
   P1OUT |= BIT1;
   P1SEL &= ~BIT1;
   P1SEL2 &= ~BIT1;

   spi_init();
   spi_mode_2();
   spi_transfer(0x00);  // Strawman xfer to cover G2452 errata USI5

   oasisdisp_init(&P1OUT, BIT1, 7);

   oasisdisp_print_word(&P1OUT, BIT1, (uint16_t) &biznatch);

   LPM4;
   return 0;
}

 

Pic of this example:

post-15991-0-58265200-1353033521_thumb.jpg

Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...