diff --git a/docs/images/p9813.jpg b/docs/images/p9813.jpg new file mode 100644 index 00000000..7fecfb4e Binary files /dev/null and b/docs/images/p9813.jpg differ diff --git a/doxy/samples.mapping.txt b/doxy/samples.mapping.txt index 24263780..76b8da54 100644 --- a/doxy/samples.mapping.txt +++ b/doxy/samples.mapping.txt @@ -73,3 +73,4 @@ water.cxx WaterSample.java water.js water.py wt5001.cxx WT5001Sample.java wt5001.js wt5001.py yg1006.cxx YG1006Sample.java yg1006.js yg1006.py sensortemplate.cxx SensorTemplateSample.java sensortemplate.js sensortemplate.py +p9813.cxx P9813Sample.java p9813.js p9813.py diff --git a/examples/c++/CMakeLists.txt b/examples/c++/CMakeLists.txt index 8e10b8d6..bb255b18 100644 --- a/examples/c++/CMakeLists.txt +++ b/examples/c++/CMakeLists.txt @@ -330,6 +330,7 @@ add_example (rf22-client) add_example (mcp2515) add_example (max30100) add_example (sensortemplate) +add_example (p9813) # These are special cases where you specify example binary, source file and module(s) include_directories (${PROJECT_SOURCE_DIR}/src) diff --git a/examples/c++/p9813.cxx b/examples/c++/p9813.cxx new file mode 100644 index 00000000..f624cc05 --- /dev/null +++ b/examples/c++/p9813.cxx @@ -0,0 +1,48 @@ +/* + * Author: Sergey Kiselev + * Copyright (c) 2017 Sergey Kiselev + * Based on the p9813 driver writen by Yannick Adam + * + * 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 "p9813.hpp" +#include +#include +#include + +using namespace std; + +int +main(int argc, char** argv) +{ + //! [Interesting] + // Instantiate a chain of 2 LEDs using pin 2 for clock and pin 3 for data + upm::P9813 ledChain(2, 2, 3); + + // Set all LEDs to Red + ledChain.setAllLeds(255, 0, 0); + + // Set a single LED to green + ledChain.setLed(1, 0, 255, 0); + + //! [Interesting] + return 0; +} diff --git a/examples/java/CMakeLists.txt b/examples/java/CMakeLists.txt index f3a239c4..2e411c26 100644 --- a/examples/java/CMakeLists.txt +++ b/examples/java/CMakeLists.txt @@ -165,6 +165,7 @@ add_example(Ads1015Sample ads1x15) add_example(MAX30100_Example max30100) add_example(Ads1115Sample ads1x15) add_example(SensorTemplateSample sensortemplate) +add_example(P9813Sample p9813) add_example_with_path(Jhd1313m1_lcdSample lcd i2clcd) add_example_with_path(Jhd1313m1Sample lcd i2clcd) diff --git a/examples/java/P9813Sample.java b/examples/java/P9813Sample.java new file mode 100644 index 00000000..ce25384b --- /dev/null +++ b/examples/java/P9813Sample.java @@ -0,0 +1,42 @@ +/* + * Author: Sergey Kiselev + * Copyright (c) 2017 Sergey Kiselev + * Based on the apa102 driver writen by Yannick Adam + * + * 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. + */ + +public class P9813Sample { + + public static void main(String[] args) throws InterruptedException { + // ! [Interesting] + // Instantiate a chain of 2 LEDs using pin 2 for clock and pin 3 for data + upm_p9813.P9813 ledChain = + new upm_p9813.P9813(2, (short)2, (short)3, false); + + System.out.println("Set all LEDs to blue"); + ledChain.setAllLeds((short)0, (short)0, (short)255); + + System.out.println("Set a single LED to red at index 1"); + ledChain.setLed(1, (short)255, (short)0, (short)0); + + // ! [Interesting] + } +} diff --git a/examples/javascript/p9813.js b/examples/javascript/p9813.js new file mode 100644 index 00000000..e1c112e6 --- /dev/null +++ b/examples/javascript/p9813.js @@ -0,0 +1,40 @@ +/* +* Author: Sergey Kiselev +* Copyright (c) 2017 Sergey Kiselev +* Based on the p9813 driver writen by Yannick Adam +* +* 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. +*/ + +var lib = require('jsupm_p9813'); + +// Instantiate a chain of 2 LEDs using pin 2 for clock and pin 3 for data +var ledChain = new lib.P9813(2, 2, 3); + +// Set all LEDs to blue +ledChain.setAllLeds(0, 0, 255); + +// Set a single led to green +ledChain.setLed(1, 0, 255, 0); + + +// Exit +ledChain = null; +process.exit(0); diff --git a/examples/python/p9813.py b/examples/python/p9813.py new file mode 100644 index 00000000..3c57affd --- /dev/null +++ b/examples/python/p9813.py @@ -0,0 +1,48 @@ +#!/usr/bin/python +# Author: Sergey Kiselev +# Copyright (c) 2016 Sergey Kiselev +# Based on the apa102 driver writen by Yannick Adam +# +# 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. + +from __future__ import print_function +import time, sys, signal, atexit +from upm import pyupm_p9813 as mylib + +def main(): + # Instantiate a chain of 2 LEDs using pin 2 for clock and pin 3 for data + ledChain = mylib.P9813(2, 2, 3) + + ## Exit handlers ## + # This stops python from printing a stacktrace when you hit control-C + def SIGINTHandler(signum, frame): + raise SystemExit + + # Register exit handlers + signal.signal(signal.SIGINT, SIGINTHandler) + + print("Setting all LEDs to Green") + ledChain.setAllLeds(0, 255, 0) + + print("Setting LED 1 to Blue") + ledChain.setLed(1, 0, 0, 255) + +if __name__ == '__main__': + main() diff --git a/src/p9813/CMakeLists.txt b/src/p9813/CMakeLists.txt new file mode 100644 index 00000000..0212e2ab --- /dev/null +++ b/src/p9813/CMakeLists.txt @@ -0,0 +1,7 @@ +upm_mixed_module_init (NAME p9813 + DESCRIPTION "P9813 Chainable RGB LEDs" + C_HDR p9813.h + C_SRC p9813.c + CPP_HDR p9813.hpp + CPP_SRC p9813.cxx + REQUIRES mraa) diff --git a/src/p9813/javaupm_p9813.i b/src/p9813/javaupm_p9813.i new file mode 100644 index 00000000..1d422c5c --- /dev/null +++ b/src/p9813/javaupm_p9813.i @@ -0,0 +1,20 @@ +%module javaupm_p9813 + +%include "../upm.i" +%include "typemaps.i" + +%{ + #include "p9813.hpp" +%} +%include "p9813.hpp" + +%pragma(java) jniclasscode=%{ + static { + try { + System.loadLibrary("javaupm_p9813"); + } catch (UnsatisfiedLinkError e) { + System.err.println("Native code library failed to load. \n" + e); + System.exit(1); + } + } +%} diff --git a/src/p9813/jsupm_p9813.i b/src/p9813/jsupm_p9813.i new file mode 100644 index 00000000..9d4cf8f9 --- /dev/null +++ b/src/p9813/jsupm_p9813.i @@ -0,0 +1,7 @@ +%module jsupm_p9813 +%include "../upm.i" + +%include "p9813.hpp" +%{ + #include "p9813.hpp" +%} diff --git a/src/p9813/p9813.c b/src/p9813/p9813.c new file mode 100644 index 00000000..cc7af954 --- /dev/null +++ b/src/p9813/p9813.c @@ -0,0 +1,149 @@ +/* + * Author: Sergey Kiselev + * Copyright (c) 2017 Sergey Kiselev + * + * 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 +#include + +#include "p9813.h" + +p9813_context p9813_init(int ledcount, int clk, int data) { + + p9813_context dev = (p9813_context)malloc(sizeof(struct _p9813_context)); + + if(!dev) + return NULL; + + memset(dev, 0, sizeof(struct _p9813_context)); + dev->leds = ledcount; + + // Try to allocate and zero out buffer + if ((dev->buffer = (uint8_t*)malloc(dev->leds * 3))) { + memset(dev->buffer, 0x00, dev->leds * 3); + } else { + printf("%s: Failed to allocate LED buffer.\n", __FUNCTION__); + p9813_close(dev); + return NULL; + } + + dev->clk = NULL; + dev->data = NULL; + + if (!(dev->clk = mraa_gpio_init(clk))) { + printf("%s: mraa_gpio_init(clk) failed.\n", __FUNCTION__); + p9813_close(dev); + return NULL; + } + mraa_gpio_dir(dev->clk, MRAA_GPIO_OUT); + + if (!(dev->data = mraa_gpio_init(data))) { + printf("%s: mraa_gpio_init(data) failed.\n", __FUNCTION__); + p9813_close(dev); + return NULL; + } + + return dev; +} + +void p9813_close(p9813_context dev) { + assert(dev != NULL); + + if (dev->clk) + mraa_gpio_close(dev->clk); + if (dev->data) + mraa_gpio_close(dev->data); + if(dev->buffer) + free(dev->buffer); + free(dev); +} + +upm_result_t p9813_set_led(p9813_context dev, uint16_t index, uint8_t r, uint8_t g, uint8_t b) { + return p9813_set_leds(dev, index, index, r, g, b); +} + +upm_result_t p9813_set_leds(p9813_context dev, uint16_t s_index, uint16_t e_index, uint8_t r, uint8_t g, uint8_t b) { + assert(dev != NULL); + int i; + + for (i = s_index; i <= e_index; i++) { + dev->buffer[i * 3] = r; + dev->buffer[i * 3 + 1] = g; + dev->buffer[i * 3 + 2] = b; + } + return UPM_SUCCESS; +} + +upm_result_t p9813_send_byte(p9813_context dev, uint8_t data) +{ + for (uint16_t i = 0; i < 8; i++) { + // Write the data bit + mraa_gpio_write(dev->data, (data & 0x80) >> 7); + // Pulse the clock + mraa_gpio_write(dev->clk, 1); + usleep(20); + mraa_gpio_write(dev->clk, 0); + usleep(20); + + // Shift to the next data bit + data <<= 1; + } + + return UPM_SUCCESS; +} + + +upm_result_t p9813_refresh(p9813_context dev) { + uint16_t i; + uint8_t byte0, red, green, blue; + + assert(dev != NULL); + + // Begin data frame + p9813_send_byte(dev, 0x00); + p9813_send_byte(dev, 0x00); + p9813_send_byte(dev, 0x00); + p9813_send_byte(dev, 0x00); + + for (i = 0; i <= dev->leds; i++) { + red = dev->buffer[i * 3]; + green = dev->buffer[i * 3 + 1]; + blue = dev->buffer[i * 3 + 2]; + // The first byte is 11 followed by inverted bits 7 and 6 of blue, green, and red + byte0 = 0xFF; + byte0 ^= (blue >> 2) & 0x30; // XOR bits 4-5 + byte0 ^= (green >> 4) & 0xC0; // XOR bits 2-3 + byte0 ^= (red >> 6) & 0x03; // XOR bits 0-1 + p9813_send_byte(dev, byte0); + p9813_send_byte(dev, blue); + p9813_send_byte(dev, green); + p9813_send_byte(dev, red); + } + + // End data frame + p9813_send_byte(dev, 0x00); + p9813_send_byte(dev, 0x00); + p9813_send_byte(dev, 0x00); + p9813_send_byte(dev, 0x00); + + return UPM_SUCCESS; +} diff --git a/src/p9813/p9813.cxx b/src/p9813/p9813.cxx new file mode 100644 index 00000000..4f74c4e0 --- /dev/null +++ b/src/p9813/p9813.cxx @@ -0,0 +1,146 @@ +/* + * Author: Sergey Kiselev + * Copyright (c) 2017 Sergey Kiselev + * Based on the apa102 driver writen by Yannick Adam + * + * 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 +#include +#include +#include +#include + +#include "p9813.hpp" + +using namespace upm; + +P9813::P9813(uint16_t ledCount, uint16_t clkPin, uint16_t dataPin, bool batchMode) + : m_leds(ledCount), m_clkGpio(clkPin), m_dataGpio(dataPin), m_batchMode(batchMode) +{ + mraa::Result res = mraa::SUCCESS; + + // Set GPIO pins to output direction + res = m_clkGpio.dir(mraa::DIR_OUT); + if (res != mraa::SUCCESS) { + throw std::invalid_argument(std::string(__FUNCTION__) + + ": GPIO failed to set direction"); + } + res = m_dataGpio.dir(mraa::DIR_OUT); + if (res != mraa::SUCCESS) { + throw std::invalid_argument(std::string(__FUNCTION__) + + ": GPIO failed to set direction"); + } +} + +void +P9813::setLed(uint16_t ledIdx, uint8_t r, uint8_t g, uint8_t b) +{ + setLeds(ledIdx, ledIdx, r, g, b); +} + +void +P9813::setAllLeds(uint8_t r, uint8_t g, uint8_t b) +{ + setLeds(0, m_leds.size() - 1, r, g, b); +} + +void +P9813::setLeds(uint16_t startIdx, uint16_t endIdx, uint8_t r, uint8_t g, uint8_t b) +{ + for (uint16_t i = startIdx; i <= endIdx; i++) { + m_leds[i].red = r; + m_leds[i].green = g; + m_leds[i].blue = b; + } + + if (!m_batchMode) { + pushState(); + } +} + +void +P9813::setLeds(uint16_t startIdx, uint16_t endIdx, std::vector colors) +{ + for (uint16_t i = startIdx, j = 0; i <= endIdx; i++) { + m_leds[i].red = colors[j].red; + m_leds[i].green = colors[j].green; + m_leds[i].blue = colors[j].blue; + } + + if (!m_batchMode) { + pushState(); + } +} + +void +P9813::pushState(void) +{ + // Begin data frame + sendByte(0x00); + sendByte(0x00); + sendByte(0x00); + sendByte(0x00); + + for (uint16_t i = 0; i <= m_leds.size(); i++) { + uint8_t red = m_leds[i].red; + uint8_t green = m_leds[i].green; + uint8_t blue = m_leds[i].blue; + // The first byte is 11 followed by inverted bits 7 and 6 of blue, green, and red + uint8_t byte0 = 0xFF; + byte0 ^= (blue >> 2) & 0x30; // XOR bits 4-5 + byte0 ^= (green >> 4) & 0xC0; // XOR bits 2-3 + byte0 ^= (red >> 6) & 0x03; // XOR bits 0-1 + sendByte(byte0); + sendByte(blue); + sendByte(green); + sendByte(red); + } + + // End data frame + sendByte(0x00); + sendByte(0x00); + sendByte(0x00); + sendByte(0x00); +} + +/* + * ************** + * private area + * ************** +*/ + +void +P9813::sendByte(uint8_t data) +{ + for (uint16_t i = 0; i < 8; i++) { + // Write the data bit + m_dataGpio.write((data & 0x80) >> 7); + // Pulse the clock + m_clkGpio.write(1); + usleep(20); + m_clkGpio.write(0); + usleep(20); + + // Shift to the next data bit + data <<= 1; + } +} diff --git a/src/p9813/p9813.h b/src/p9813/p9813.h new file mode 100644 index 00000000..c11f32c4 --- /dev/null +++ b/src/p9813/p9813.h @@ -0,0 +1,106 @@ +/* + * Author: Sergey Kiselev + * Copyright (c) 2017 Sergey Kiselev + * + * 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 +#include "upm.h" +#include "mraa/gpio.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @file p9813.h + * @library p9813 + * @brief C API for controlling P9813/Chainable RGN LEDs + * + * @include p9813.c + */ + +/** + * Device context + */ +typedef struct _p9813_context { + // clock and data GPIO pins + mraa_gpio_context clk, data; + + uint8_t* buffer; + int leds; +} *p9813_context; + + +/** + * Instantiates a new P9813 Chainable RGB LEDs + * + * @param ledcount Number of LEDs in the chain + * @param clk Clock pin + * @param data Data pin + * @return an initialized p9813 context on success, NULL on error. + */ +p9813_context p9813_init(int ledcount, int clk, int data); + +/** + * P9813 close function + * + * @param dev The p9813_context to close + */ +void p9813_close(p9813_context dev); + +/** + * Sets the color for one LED in the buffer + * + * @param dev The p9813_context to use + * @param index Index of the LED (0 based) + * @param r Red component (0-255) + * @param g Green component (0-255) + * @param b Blue component (0-255) + * @return upm_result_t UPM success/error code + */ +upm_result_t p9813_set_led(p9813_context dev, uint16_t index, uint8_t r, uint8_t g, uint8_t b); + +/** + * Sets the color for multiple LEDs in the buffer + * + * @param dev The p9813_context to use + * @param s_index The start Index of the LED range (0 based) + * @param e_index The end Index of the LED range (0 based) + * @param r Red component (0-255) + * @param g Green component (0-255) + * @param b Blue component (0-255) + * @return upm_result_t UPM success/error code + */ +upm_result_t p9813_set_leds(p9813_context dev, uint16_t s_index, uint16_t e_index, uint8_t r, uint8_t g, uint8_t b); + +/** + * Writes the buffer to the LED controllers thus updating the LEDs + * + * @param dev The p9813_context to use + * @return upm_result_t UPM success/error code + */ +upm_result_t p9813_refresh(p9813_context dev); + +#ifdef __cplusplus +} +#endif diff --git a/src/p9813/p9813.hpp b/src/p9813/p9813.hpp new file mode 100644 index 00000000..2949106e --- /dev/null +++ b/src/p9813/p9813.hpp @@ -0,0 +1,136 @@ +/* + * Author: Sergey Kiselev + * Copyright (c) 2017 Sergey Kiselev + * Based on the apa102 driver writen by Yannick Adam + * + * 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 +#include + +namespace upm +{ +/** + * @brief P9813 Chainable RGB LEDs driver library + * @defgroup p9813 libupm-p9813 + * @ingroup adafruit gpio led + */ + +typedef struct { + uint8_t red, green, blue; +} RgbColor; + +/** + * @library p9813 + * @sensor p9813 + * @comname Chainable RGB LED driver + * @type led + * @man adafruit + * @con gpio + * @web https://www.adafruit.com/product/2343 + * + * @brief API for controlling P9813/Chainable RGB LEDs + * + * P9813 LED controller provides individually controllable LEDs through a two pin protocol + * For each LED, an RGB (0-255) value can be set. + * + * @image html p9813.jpg + * @snippet p9813.cxx Interesting + */ +class P9813 +{ + public: + /** + * Instantiates a new P9813 LED chain + * + * @param ledCount Number of P9813 leds in the chain + * @param clkPin Clock Pin + * @param dataPin Data Pin + * @param batchMode (optional) Immediately write to the LED controllers (false, default) or wait for a pushState + * call (true) + * @param csn (optional) Chip Select Pin + */ + P9813(uint16_t ledCount, uint16_t clkPin, uint16_t dataPin, bool batchMode = false); + + /** + * P9813 destructor + */ + virtual ~P9813() {}; + + /** + * Set the color for a single LED + * + * @param ledIdx Index of the LED in the chain (0 based) + * @param r Red component (0-255) + * @param g Green component (0-255) + * @param b Blue component (0-255) + */ + void setLed(uint16_t ledIdx, uint8_t r, uint8_t g, uint8_t b); + + /** + * Set the color for all LEDs + * + * @param r Red component (0-255) + * @param g Green component (0-255) + * @param b Blue component (0-255) + */ + void setAllLeds(uint8_t r, uint8_t g, uint8_t b); + + /** + * Set the color for a range of LEDs + * + * @param startIdx Start index of the range of LEDs in the chain (0 based) + * @param endIdx End index of the range of LEDs in the chain (0 based) + * @param r Red component (0-255) + * @param g Green component (0-255) + * @param b Blue component (0-255) + */ + void + setLeds(uint16_t startIdx, uint16_t endIdx, uint8_t r, uint8_t g, uint8_t b); + + /** + * (Advanced) Manually control the colors and brightness of a range of LEDS + * Best used to maximize performance + * + * @param startIdx Start index of the range of LEDs to update (0 based) + * @param endIdx End index of the range of LEDs to update (0 based) + * @param colors Vector containing RgbColor structures for each LED + * No check done on the boundaries + */ + void setLeds(uint16_t startIdx, uint16_t endIdx, std::vector colors); + + /** + * Outputs the current LED data to the LED controllers + * Note: Only required if batch mode is set to TRUE + * + */ + void pushState(); + + private: + std::vector m_leds; + mraa::Gpio m_clkGpio; + mraa::Gpio m_dataGpio; + bool m_batchMode; + + void sendByte(uint8_t data); +}; +} diff --git a/src/p9813/p9813_fti.c b/src/p9813/p9813_fti.c new file mode 100644 index 00000000..2257fa3a --- /dev/null +++ b/src/p9813/p9813_fti.c @@ -0,0 +1,67 @@ +/* + * Author: Mihai Tudor Panu + * 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 "p9813.h" +#include "upm_fti.h" + +/** + * This file implements the Function Table Interface (FTI) for this sensor + */ + +const char upm_p9813_name[] = "P9813"; +const char upm_p9813_description[] = "P9813/Chainable RGB LEDs"; +const upm_protocol_t upm_p9813_protocol[] = {UPM_GPIO}; +const upm_sensor_t upm_p9813_category[] = {}; + +// forward declarations +const void* upm_p9813_get_ft(upm_sensor_t sensor_type); +void* upm_p9813_init_name(); +void upm_p9813_close(void *dev); + +static const upm_sensor_ft ft = +{ + .upm_sensor_init_name = &upm_p9813_init_name, + .upm_sensor_close = &upm_p9813_close, +}; + +const void* upm_p9813_get_ft(upm_sensor_t sensor_type) +{ + switch(sensor_type) + { + case UPM_SENSOR: + return &ft; + default: + return NULL; + } +} + +void* upm_p9813_init_name() +{ + return NULL; +} + +void upm_p9813_close(void *dev) +{ + p9813_close((p9813_context)dev); +} diff --git a/src/p9813/pyupm_p9813.i b/src/p9813/pyupm_p9813.i new file mode 100644 index 00000000..8cbc6337 --- /dev/null +++ b/src/p9813/pyupm_p9813.i @@ -0,0 +1,11 @@ +// Include doxygen-generated documentation +%include "pyupm_doxy2swig.i" +%module pyupm_p9813 +%include "../upm.i" + +%feature("autodoc", "3"); + +%include "p9813.hpp" +%{ + #include "p9813.hpp" +%}