my9221: C implementation; C example; C++ wraps C

Signed-off-by: Jon Trulson <jtrulson@ics.com>
This commit is contained in:
Jon Trulson 2016-11-08 17:11:25 -07:00
parent fde727b601
commit 54771e63c1
10 changed files with 712 additions and 261 deletions

View File

@ -137,6 +137,7 @@ add_example (guvas12d)
add_example (otp538u)
add_example (button)
add_example (button_intr)
add_example (my9221)
# Custom examples
add_custom_example (nmea_gps_i2c-example-c nmea_gps_i2c.c nmea_gps)

89
examples/c/my9221.c Normal file
View File

@ -0,0 +1,89 @@
/*
* Author: Jon Trulson <jtrulson@ics.com>
* Copyright (c) 2016 Intel Corporation.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <unistd.h>
#include <stdio.h>
#include <signal.h>
#include <upm_utilities.h>
#include <my9221.h>
int shouldRun = true;
void sig_handler(int signo)
{
if (signo == SIGINT)
shouldRun = false;
}
int main ()
{
signal(SIGINT, sig_handler);
//! [Interesting]
// Instantiate a GroveLEDBar, we use D8 for the data, and D9 for the
// clock. We only use a single instance.
my9221_context leds = my9221_init(8, 9, 1);
if (!leds)
{
printf("my9221_init() failed\n");
return 1;
}
while (shouldRun)
{
// count up
printf("Counting up: ");
for (int i=0; i<my9221_get_max_leds(leds); i++)
{
printf("%d ", i);
my9221_clear_all(leds);
my9221_set_led(leds, i, true);
upm_delay_ms(100);
}
printf("\n");
upm_delay_ms(100);
// count down
printf("Counting down: ");
for (int i=my9221_get_max_leds(leds) - 1; i>=0; i--)
{
printf("%d ", i);
my9221_clear_all(leds);
my9221_set_led(leds, i, true);
upm_delay_ms(100);
}
printf("\n");
upm_delay_ms(100);
}
printf("Exiting...\n");
my9221_close(leds);
//! [Interesting]
return 0;
}

View File

@ -1,5 +1,8 @@
set (libname "my9221")
set (libdescription "12-channel (RBG x 4) constant current LED driver with grayscale")
set (module_src ${libname}.cxx groveledbar.cxx grovecircularled.cxx)
set (module_hpp ${libname}.hpp groveledbar.hpp grovecircularled.hpp)
upm_module_init()
upm_mixed_module_init (NAME my9221
DESCRIPTION "12-channel constant current LED driver with grayscale"
C_HDR my9221.h
C_SRC my9221.c
CPP_HDR my9221.hpp groveledbar.hpp grovecircularled.hpp
CPP_SRC my9221.cxx groveledbar.cxx grovecircularled.cxx
CPP_WRAPS_C
REQUIRES mraa)

View File

@ -45,11 +45,11 @@ using namespace upm;
using namespace std;
GroveCircularLED::GroveCircularLED (uint8_t dataPin, uint8_t clockPin)
: MY9221(dataPin, clockPin, 2)
: MY9221(dataPin, clockPin, 2)
{
// auto refresh by default
setAutoRefresh(true);
clearAll();
// auto refresh by default
setAutoRefresh(true);
clearAll();
}
GroveCircularLED::~GroveCircularLED()
@ -58,37 +58,44 @@ GroveCircularLED::~GroveCircularLED()
void GroveCircularLED::setSpinner(uint8_t position)
{
if (position > 23)
position = 23;
if (position > 23)
position = 23;
for (uint8_t i=0; i<(LEDS_PER_INSTANCE * m_instances); i++)
m_bitStates[i] = (i == position) ? m_highIntensity : m_lowIntensity;
unsigned int ledsPerInstance = m_my9221->max_leds_per_instance;
if (m_autoRefresh)
refresh();
for (uint8_t i=0; i<(ledsPerInstance * m_my9221->instances); i++)
m_my9221->bitStates[i] =
(i == position) ? m_my9221->highIntensity : m_my9221->lowIntensity;
return;
if (m_my9221->autoRefresh)
refresh();
return;
}
void GroveCircularLED::setLevel(uint8_t level, bool direction)
{
if (level > 23)
level = 23;
if (level > 23)
level = 23;
if (!direction)
unsigned int ledsPerInstance = m_my9221->max_leds_per_instance;
if (!direction)
{
for (int i=0; i < static_cast<int>(LEDS_PER_INSTANCE * m_instances); i++)
m_bitStates[i] = (i < level) ? m_highIntensity : m_lowIntensity;
for (unsigned int i=0; i < (ledsPerInstance * m_my9221->instances); i++)
m_my9221->bitStates[i] =
(i < level) ? m_my9221->highIntensity : m_my9221->lowIntensity;
}
else
else
{
for (int i=0; i< static_cast<int>(LEDS_PER_INSTANCE * m_instances); i++)
m_bitStates[i] = (((LEDS_PER_INSTANCE * m_instances) - i) <= level)
? m_highIntensity : m_lowIntensity;
for (unsigned int i=0; i<(ledsPerInstance * m_my9221->instances); i++)
m_my9221->bitStates[i] =
(((ledsPerInstance * m_my9221->instances) - i) <= level)
? m_my9221->highIntensity : m_my9221->lowIntensity;
}
if (m_autoRefresh)
refresh();
if (m_my9221->autoRefresh)
refresh();
return;
return;
}

View File

@ -45,44 +45,47 @@ using namespace upm;
using namespace std;
GroveLEDBar::GroveLEDBar (uint8_t dataPin, uint8_t clockPin, int instances)
: MY9221(dataPin, clockPin, instances)
: MY9221(dataPin, clockPin, instances)
{
// auto refresh by default
setAutoRefresh(true);
clearAll();
// auto refresh by default
setAutoRefresh(true);
clearAll();
}
GroveLEDBar::~GroveLEDBar()
{
}
void GroveLEDBar::setBarLevel(uint8_t level, bool greenToRed, int barNumber)
void GroveLEDBar::setBarLevel(uint8_t level, bool greenToRed,
unsigned int barNumber)
{
if (level > 10)
level = 10;
// here we manipulate the my9221 context struct directly
if (level > 10)
level = 10;
if (barNumber >= static_cast<int>(m_instances))
barNumber = m_instances - 1;
if (barNumber >= m_my9221->instances)
barNumber = m_my9221->instances - 1;
int start = barNumber * LEDS_PER_INSTANCE;
int end = start + LEDS_PER_INSTANCE;
unsigned int ledsPerInstance = m_my9221->max_leds_per_instance;
unsigned int start = barNumber * ledsPerInstance;
unsigned int end = start + ledsPerInstance;
if (!greenToRed)
if (!greenToRed)
{
for (int i=start; i<end; i++)
m_bitStates[i] = (i < (level + start)) ?
m_highIntensity : m_lowIntensity;
for (unsigned int i=start; i<end; i++)
m_my9221->bitStates[i] = (i < (level + start)) ?
m_my9221->highIntensity : m_my9221->lowIntensity;
}
else
else
{
for (int i=start; i<end; i++)
m_bitStates[i] = ( ((start + LEDS_PER_INSTANCE) - i) <=
(level + 2 + start)) ?
m_highIntensity : m_lowIntensity;
for (unsigned int i=start; i<end; i++)
m_my9221->bitStates[i] = ( ((start + ledsPerInstance) - i) <=
(level + 2 + start)) ?
m_my9221->highIntensity : m_my9221->lowIntensity;
}
if (m_autoRefresh)
refresh();
if (m_my9221->autoRefresh)
refresh();
return;
return;
}

View File

@ -90,7 +90,8 @@ namespace upm {
* together, this argument selects a specific bar starting at 0.
* The default is 0.
*/
void setBarLevel(uint8_t level, bool greenToRed=true, int barNumber=0);
void setBarLevel(uint8_t level, bool greenToRed=true,
unsigned int barNumber=0);
protected:
private:

287
src/my9221/my9221.c Normal file
View File

@ -0,0 +1,287 @@
/*
* Author: Jon Trulson <jtrulson@ics.com>
* Copyright (c) 2016 Intel Corporation.
*
* These modules were rewritten, based on original work by:
*
* (original my9221/groveledbar driver)
* Author: Yevgeniy Kiveisha <yevgeniy.kiveisha@intel.com>
* Copyright (c) 2014 Intel Corporation.
*
* (grovecircularled driver)
* Author: Jun Kato and Yevgeniy Kiveisha <yevgeniy.kiveisha@intel.com>
* Contributions: Jon Trulson <jtrulson@ics.com>
* Copyright (c) 2014 Intel Corporation.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <assert.h>
#include <string.h>
#include <upm_utilities.h>
#include <upm_platform.h>
#include "my9221.h"
// 12 LED channels per chip (instance)
#define LEDS_PER_INSTANCE (12)
// forward declarations
static void my9221_lock_data(const my9221_context dev);
static void my9221_send_16bit_block(const my9221_context dev, uint16_t data);
my9221_context my9221_init(uint8_t dataPin, uint8_t clockPin,
int instances)
{
if (instances < 1)
instances = 1;
my9221_context dev =
(my9221_context)malloc(sizeof(struct _my9221_context));
if (!dev)
return NULL;
memset((void *)dev, 0, sizeof(struct _my9221_context));
dev->gpioClk = NULL;
dev->gpioData = NULL;
// make sure MRAA is initialized
mraa_result_t mraa_rv;
if ((mraa_rv = mraa_init()) != MRAA_SUCCESS)
{
printf("%s: mraa_init() failed (%d).\n", __FUNCTION__, mraa_rv);
my9221_close(dev);
return NULL;
}
// MRAA contexts...
if ( !(dev->gpioClk = mraa_gpio_init(clockPin)) )
{
printf("%s: mraa_gpio_init(clk) failed\n",
__FUNCTION__);
my9221_close(dev);
return NULL;
}
mraa_gpio_dir(dev->gpioClk, MRAA_GPIO_OUT);
if ( !(dev->gpioData = mraa_gpio_init(dataPin)) )
{
printf("%s: mraa_gpio_init(data) failed\n",
__FUNCTION__);
my9221_close(dev);
return NULL;
}
mraa_gpio_dir(dev->gpioData, MRAA_GPIO_OUT);
#if defined(UPM_PLATFORM_LINUX)
// we warn if these fail, since it may not be possible to handle
// more than one instance
if (mraa_gpio_use_mmaped(dev->gpioClk, 1))
printf("%s: Warning: mmap of Clk pin failed, correct operation "
"may be affected.\n", __FUNCTION__);
if (mraa_gpio_use_mmaped(dev->gpioData, 1))
printf("%s: Warning: mmap of Data pin failed, correct operation "
"may be affected.\n", __FUNCTION__);
#endif // UPM_PLATFORM_LINUX
my9221_set_low_intensity_value(dev, 0x00); // full off
my9221_set_high_intensity_value(dev, 0xff); // full bright
dev->commandWord = 0x0000; // all defaults
dev->instances = instances;
dev->max_leds_per_instance = LEDS_PER_INSTANCE;
if ( !(dev->bitStates =
malloc(sizeof(uint16_t) * instances * LEDS_PER_INSTANCE) ) )
{
printf("%s: bit state allocation failed\n",
__FUNCTION__);
my9221_close(dev);
return NULL;
}
my9221_set_auto_refresh(dev, true);
my9221_clear_all(dev);
dev->maxLEDS = dev->instances * LEDS_PER_INSTANCE;
dev->initialized = true;
return dev;
}
void my9221_close(my9221_context dev)
{
assert(dev != NULL);
if (dev->initialized)
{
my9221_clear_all(dev);
if (!dev->autoRefresh)
my9221_refresh(dev);
}
if (dev->bitStates)
free(dev->bitStates);
if (dev->gpioClk)
mraa_gpio_close(dev->gpioClk);
if (dev->gpioData)
mraa_gpio_close(dev->gpioData);
free(dev);
}
void my9221_set_led(const my9221_context dev, int led, bool on)
{
assert(dev != NULL);
int maxLed = dev->maxLEDS - 1;
if (led > maxLed)
led = maxLed;
if (led < 0)
led = 0;
dev->bitStates[led] = (on) ? dev->highIntensity : dev->lowIntensity;
if (dev->autoRefresh)
my9221_refresh(dev);
}
void my9221_set_low_intensity_value(const my9221_context dev,
int intensity)
{
assert(dev != NULL);
dev->lowIntensity = (intensity & 0xff);
}
void my9221_set_high_intensity_value(const my9221_context dev,
int intensity)
{
assert(dev != NULL);
dev->highIntensity = (intensity & 0xff);
}
void my9221_set_all(const my9221_context dev)
{
assert(dev != NULL);
for (unsigned int i=0; i<dev->maxLEDS; i++)
dev->bitStates[i] = dev->highIntensity;
if (dev->autoRefresh)
my9221_refresh(dev);
}
void my9221_clear_all(const my9221_context dev)
{
assert(dev != NULL);
for (unsigned int i=0; i<dev->maxLEDS; i++)
dev->bitStates[i] = dev->lowIntensity;
if (dev->autoRefresh)
my9221_refresh(dev);
}
void my9221_refresh(const my9221_context dev)
{
assert(dev != NULL);
for (unsigned int i=0; i<dev->maxLEDS; i++)
{
if (i % 12 == 0)
{
my9221_send_16bit_block(dev, dev->commandWord);
}
my9221_send_16bit_block(dev, dev->bitStates[i]);
}
my9221_lock_data(dev);
}
void my9221_set_auto_refresh(const my9221_context dev, bool enable)
{
assert(dev != NULL);
dev->autoRefresh = enable;
}
int my9221_get_max_leds(const my9221_context dev)
{
assert(dev != NULL);
return dev->maxLEDS;
}
static void my9221_lock_data(const my9221_context dev)
{
assert(dev != NULL);
mraa_gpio_write(dev->gpioData, 0);
upm_delay_us(220);
for (int idx = 0; idx < 4; idx++)
{
mraa_gpio_write(dev->gpioData, 1);
mraa_gpio_write(dev->gpioData, 0);
}
// in reality, we only need > 200ns + (dev->instances * 10ns), so the
// following should be good for up to dev->instances < 80), if the
// datasheet is to be believed :)
upm_delay_us(1);
return;
}
static void my9221_send_16bit_block(const my9221_context dev, uint16_t data)
{
assert(dev != NULL);
for (uint8_t bit_idx = 0; bit_idx < 16; bit_idx++)
{
uint32_t state = (data & 0x8000) ? 1 : 0;
mraa_gpio_write(dev->gpioData, state);
state = mraa_gpio_read(dev->gpioClk);
if (state)
state = 0;
else
state = 1;
mraa_gpio_write(dev->gpioClk, state);
data <<= 1;
}
return;
}

View File

@ -44,148 +44,47 @@
using namespace upm;
using namespace std;
MY9221::MY9221 (uint8_t dataPin, uint8_t clockPin, int instances)
: m_gpioData(dataPin), m_gpioClk(clockPin), m_bitStates(0)
MY9221::MY9221 (uint8_t dataPin, uint8_t clockPin, int instances) :
m_my9221(my9221_init(dataPin, clockPin, instances))
{
if (instances < 1)
{
throw std::out_of_range(std::string(__FUNCTION__) +
": instances must be at least 1");
}
if (!m_my9221)
throw std::runtime_error(std::string(__FUNCTION__) +
": my9221_init() failed");
// set directions
m_gpioClk.dir(mraa::DIR_OUT);
m_gpioData.dir(mraa::DIR_OUT);
// we warn if these fail, since it may not be possible to handle
// more than one instance
if (m_gpioClk.useMmap(true) != mraa::SUCCESS)
cerr << __FUNCTION__
<< ": Warning: mmap of Clk pin failed, correct operation "
<< "may be affected."
<< endl;
if (m_gpioData.useMmap(true) != mraa::SUCCESS)
cerr << __FUNCTION__
<< ": Warning: mmap of Data pin failed, correct operation "
<< "may be affected."
<< endl;
setLowIntensityValue(0x00); // full off
setHighIntensityValue(0xff); // full brightness
m_commandWord = 0x0000; // all defaults
m_instances = instances;
m_bitStates = new uint16_t[instances * LEDS_PER_INSTANCE];
setAutoRefresh(true);
clearAll();
}
MY9221::~MY9221()
{
clearAll();
if (!m_autoRefresh)
refresh();
delete m_bitStates;
my9221_close(m_my9221);
}
void MY9221::setLED(int led, bool on)
{
int maxLed = (LEDS_PER_INSTANCE * m_instances) - 1;
if (led > maxLed)
led = maxLed;
if (led < 0)
led = 0;
m_bitStates[led] = (on) ? m_highIntensity : m_lowIntensity;
if (m_autoRefresh)
refresh();
my9221_set_led(m_my9221, led, on);
}
void MY9221::setLowIntensityValue(int intensity)
{
m_lowIntensity = (intensity & 0xff);
my9221_set_low_intensity_value(m_my9221, intensity);
}
void MY9221::setHighIntensityValue(int intensity)
{
m_highIntensity = (intensity & 0xff);
my9221_set_high_intensity_value(m_my9221, intensity);
}
void MY9221::setAll()
{
for (int i=0; i< static_cast<int>(m_instances * LEDS_PER_INSTANCE); i++)
m_bitStates[i] = m_highIntensity;
if (m_autoRefresh)
refresh();
my9221_set_all(m_my9221);
}
void MY9221::clearAll()
{
for (int i=0; i< static_cast<int>(m_instances * LEDS_PER_INSTANCE); i++)
m_bitStates[i] = m_lowIntensity;
if (m_autoRefresh)
refresh();
my9221_clear_all(m_my9221);
}
void MY9221::refresh()
{
for (int i=0; i< static_cast<int>(m_instances * LEDS_PER_INSTANCE); i++)
{
if (i % 12 == 0)
{
send16bitBlock(m_commandWord);
}
send16bitBlock(m_bitStates[i]);
}
lockData();
my9221_refresh(m_my9221);
}
void MY9221::lockData()
{
m_gpioData.write(0);
usleep(220);
for(int idx = 0; idx < 4; idx++)
{
m_gpioData.write(1);
m_gpioData.write(0);
}
// in reality, we only need > 200ns + (m_instances * 10ns), so the
// following should be good for up to m_instances < 80), if the
// datasheet is to be believed :)
usleep(1);
return;
}
void MY9221::send16bitBlock(uint16_t data)
{
for (uint8_t bit_idx = 0; bit_idx < 16; bit_idx++)
{
uint32_t state = (data & 0x8000) ? 1 : 0;
m_gpioData.write(state);
state = m_gpioClk.read();
if (state)
state = 0;
else
state = 1;
m_gpioClk.write(state);
data <<= 1;
}
return;
}

183
src/my9221/my9221.h Normal file
View File

@ -0,0 +1,183 @@
/*
* Author: Jon Trulson <jtrulson@ics.com>
* Copyright (c) 2016 Intel Corporation.
*
* These modules were rewritten, based on original work by:
*
* (original my9221/groveledbar)
* Author: Yevgeniy Kiveisha <yevgeniy.kiveisha@intel.com>
* Copyright (c) 2014 Intel Corporation.
*
* (grovecircularled)
* Author: Jun Kato and Yevgeniy Kiveisha <yevgeniy.kiveisha@intel.com>
* Contributions: Jon Trulson <jtrulson@ics.com>
* Copyright (c) 2014 Intel Corporation.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <stdlib.h>
#include <stdio.h>
#include <upm.h>
#include <mraa/gpio.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* @file my9221.h
* @library my9221
* @brief C API for the my9221 driver
*
* @include my9221.c
*/
/**
* Device context
*/
typedef struct _my9221_context {
mraa_gpio_context gpioClk;
mraa_gpio_context gpioData;
bool autoRefresh;
// we're only doing 8-bit greyscale, so the high order bits are
// always 0
uint16_t lowIntensity;
uint16_t highIntensity;
unsigned int instances;
unsigned int maxLEDS;
// an array of uint16_t's representing our bit states (on/off)
// intensities. Only the low 8 bits are used, but in the future
// 16bit support can work here as well.
uint16_t *bitStates;
uint16_t commandWord;
bool initialized;
// A helper for the users of this driver
unsigned int max_leds_per_instance;
} *my9221_context;
/**
* Instantiates an MY9221 object
*
* @param dataPin Data pin
* @param clockPin Clock pin
* @param instances Number of daisy-chained my9221s, must be at
* least 1
* @return Device context
*/
my9221_context my9221_init(uint8_t dataPin, uint8_t clockPin,
int instances);
/**
* MY9221 close
*
* @param dev Device context
*/
void my9221_close(my9221_context dev);
/**
* Enable or disable auto refresh. When auto refresh is enabled,
* update the LED display as soon as the internal state changes.
* When false, the display(s) will not be updated until the
* refresh() method is called.
*
* @param dev Device context
* @param enable true to enable auto refresh, false otherwise
*/
void my9221_set_auto_refresh(const my9221_context dev, bool enable);
/**
* Set an LED to a specific on (high intensity) or off (low
* intensity) value.
*
* @param dev Device context
* @param led The LED whose state you wish to change
* @param on true to turn on the LED, false to turn the LED off
*/
void my9221_set_led(const my9221_context dev, int led, bool on);
/**
* Set the greyscale intensity of an LED in the OFF state. The
* intensity is a value from 0 (fully off) to 255 (fully on).
* This will take effect on any future LED set or clear
* operations.
*
* @param dev Device context
* @param intensity a value from 0 (fully off) to 255 (fully on)
*/
void my9221_set_low_intensity_value(const my9221_context dev,
int intensity);
/**
* Set the greyscale intensity of an LED in the ON state. The
* intensity is a value from 0 (fully off) to 255 (fully on).
* This will take effect on any future LED set or clear
* operations.
*
* @param dev Device context
* @param intensity a value from 0 (fully off) to 255 (fully on)
*/
void my9221_set_high_intensity_value(const my9221_context dev,
int intensity);
/**
* Set all of the LEDS to the ON (high intensity value) state.
*
* @param dev Device context
*/
void my9221_set_all(const my9221_context dev);
/**
* Set all of the LEDS to the OFF (low intensity value) state.
*
* @param dev Device context
*/
void my9221_clear_all(const my9221_context dev);
/**
* Set the LED states to match the internal stored states. This
* is useful when auto refresh (setAutoRefresh()) is false to
* update the display.
*
* @param dev Device context
*/
void my9221_refresh(const my9221_context dev);
/**
* Return the maximum number of LEDs present, based on the number
* of instances specified when the device context was initialized.
*
* @param dev Device context
* @return The number of LEDs that can be controlled.
*/
int my9221_get_max_leds(const my9221_context dev);
#ifdef __cplusplus
}
#endif

View File

@ -35,118 +35,96 @@
#pragma once
#include <string>
#include <mraa/common.hpp>
#include <mraa/gpio.hpp>
#include <my9221.h>
namespace upm {
/**
* @brief MY9221 LED Controller library
* @defgroup my9221 libupm-my9221
* @ingroup seeed display gpio eak
*/
class MY9221 {
public:
// 12 LED channels per chip (instance)
static const int LEDS_PER_INSTANCE = 12;
/**
* Instantiates an MY9221 object
*
* @param dataPin Data pin
* @param clockPin Clock pin
* @param instances Number of daisy-chained my9221s, default 1
* @brief MY9221 LED Controller library
* @defgroup my9221 libupm-my9221
* @ingroup seeed display gpio eak
*/
MY9221(uint8_t dataPin, uint8_t clockPin, int instances=1);
class MY9221 {
public:
/**
* MY9221 destructor
*/
virtual ~MY9221();
/**
* Instantiates an MY9221 object
*
* @param dataPin Data pin
* @param clockPin Clock pin
* @param instances Number of daisy-chained my9221s, default 1
*/
MY9221(uint8_t dataPin, uint8_t clockPin, int instances=1);
/**
* Enable or disable auto refresh. When auto refresh is enabled,
* update the LED display as soon as the internal state changes.
* When false, the display(s) will not be updated until the
* refresh() method is called.
*
* @param enable true to enable auto refresh, false otherwise
*/
void setAutoRefresh(bool enable)
{
m_autoRefresh = enable;
}
/**
* MY9221 destructor
*/
virtual ~MY9221();
/**
* Set an LED to a specific on (high intensity) or off (low
* intensity) value.
*
* @param led The LED whose state you wish to change
* @param on true to turn on the LED, false to turn the LED off
*/
void setLED(int led, bool on);
/**
* Enable or disable auto refresh. When auto refresh is enabled,
* update the LED display as soon as the internal state changes.
* When false, the display(s) will not be updated until the
* refresh() method is called.
*
* @param enable true to enable auto refresh, false otherwise
*/
void setAutoRefresh(bool enable)
{
my9221_set_auto_refresh(m_my9221, enable);
}
/**
* Set the greyscale intensity of an LED in the OFF state. The
* intensity is a value from 0 (fully off) to 255 (fully on).
* This will take effect on any future LED set or clear
* operations.
*
* @param intensity a value from 0 (fully off) to 255 (fully on)
*/
void setLowIntensityValue(int intensity);
/**
* Set an LED to a specific on (high intensity) or off (low
* intensity) value.
*
* @param led The LED whose state you wish to change
* @param on true to turn on the LED, false to turn the LED off
*/
void setLED(int led, bool on);
/**
* Set the greyscale intensity of an LED in the ON state. The
* intensity is a value from 0 (fully off) to 255 (fully on).
* This will take effect on any future LED set or clear
* operations.
*
* @param intensity a value from 0 (fully off) to 255 (fully on)
*/
void setHighIntensityValue(int intensity);
/**
* Set the greyscale intensity of an LED in the OFF state. The
* intensity is a value from 0 (fully off) to 255 (fully on).
* This will take effect on any future LED set or clear
* operations.
*
* @param intensity a value from 0 (fully off) to 255 (fully on)
*/
void setLowIntensityValue(int intensity);
/**
* Set all of the LEDS to the ON (high intensity value) state.
*/
void setAll();
/**
* Set the greyscale intensity of an LED in the ON state. The
* intensity is a value from 0 (fully off) to 255 (fully on).
* This will take effect on any future LED set or clear
* operations.
*
* @param intensity a value from 0 (fully off) to 255 (fully on)
*/
void setHighIntensityValue(int intensity);
/**
* Set all of the LEDS to the OFF (low intensity value) state.
*/
void clearAll();
/**
* Set all of the LEDS to the ON (high intensity value) state.
*/
void setAll();
/**
* Set the LED states to match the internal stored states. This
* is useful when auto refresh (setAutoRefresh()) is false to
* update the display.
*/
void refresh();
/**
* Set all of the LEDS to the OFF (low intensity value) state.
*/
void clearAll();
protected:
virtual void lockData();
virtual void send16bitBlock(uint16_t data);
/**
* Set the LED states to match the internal stored states. This
* is useful when auto refresh (setAutoRefresh()) is false to
* update the display.
*/
void refresh();
bool m_autoRefresh;
// we're only doing 8-bit greyscale, so the high order bits are
// always 0
uint16_t m_lowIntensity;
uint16_t m_highIntensity;
protected:
unsigned int m_instances;
my9221_context m_my9221;
mraa::Gpio m_gpioData;
mraa::Gpio m_gpioClk;
// an array of uint16_t's representing our bit states (on/off)
// intensities. Only the low 8 bits are used, but in the future
// 16bit support can work here as well.
uint16_t *m_bitStates;
uint16_t m_commandWord;
private:
};
private:
};
}