Преглед на файлове

my9221: rewrite to include new functionality and serve as a base class

This driver has been rewritten to support some new functionality, be
more generic and fix up some old bugs.  Multiple MY9221's can now be
chained together and are supported by the MY9221 base class.

In addition, the Grove LED Bar and Grove Circular LED drivers have
been incoporated into the my9221 library, using the new MY9221 class
as their base class.  Examples have been fixed to work with the new
library, and renamed where needed.

The current grovecircularled driver has been removed as it is now a
part of the my9221 library.

Signed-off-by: Jon Trulson <jtrulson@ics.com>
Signed-off-by: Mihai Tudor Panu <mihai.tudor.panu@intel.com>
Jon Trulson преди 9 години
родител
ревизия
cbb289438e

+ 3
- 2
examples/c++/grovecircularled.cxx Целия файл

@@ -43,9 +43,9 @@ int main()
43 43
   
44 44
 //! [Interesting]
45 45
   
46
-  // Instantiate a Grove Circular LED on gpio pins 5 and 4
46
+  // Instantiate a Grove Circular LED on D9 for data, D8 for clock
47 47
   
48
-  upm::GroveCircularLED *circle = new upm::GroveCircularLED(5, 4);
48
+  upm::GroveCircularLED *circle = new upm::GroveCircularLED(9, 8);
49 49
   
50 50
   int level = 0;
51 51
   while (shouldRun)
@@ -54,6 +54,7 @@ int main()
54 54
       level = (level + 1) % 24;
55 55
       usleep(100000);
56 56
     }
57
+
57 58
 //! [Interesting]
58 59
 
59 60
   cout << "Exiting" << endl;

+ 22
- 23
examples/c++/my9221-ledbar.cxx Целия файл

@@ -27,37 +27,36 @@
27 27
 #include "my9221.h"
28 28
 #include <signal.h>
29 29
 
30
-int running = 0;
30
+int shouldRun = true;
31 31
 
32
-void
33
-sig_handler(int signo)
32
+void sig_handler(int signo)
34 33
 {
35
-    printf("got signal\n");
36
-    if (signo == SIGINT) {
37
-        printf("exiting application\n");
38
-        running = 1;
39
-    }
34
+  if (signo == SIGINT)
35
+    shouldRun = false;
40 36
 }
41 37
 
42
-int
43
-main(int argc, char **argv)
38
+int main(int argc, char **argv)
44 39
 {
45
-    //! [Interesting]
46
-    upm::MY9221 *bar = new upm::MY9221(8, 9);
47
-
48
-    signal(SIGINT, sig_handler);
49
-
50
-    while (!running) {
51
-        for (int idx = 1; idx < 11; idx++) {
52
-            bar->setBarLevel (idx);
53
-            usleep(1000);
40
+  signal(SIGINT, sig_handler);
41
+
42
+  //! [Interesting]
43
+  upm::MY9221 *bar = new upm::MY9221(8, 9);
44
+
45
+  // Green to Red
46
+  bar->setBarDirection(true);
47
+  while (shouldRun)
48
+    {
49
+      for (int i = 0; i < 11; i++)
50
+        {
51
+          bar->setBarLevel(i);
52
+          usleep(250000);
54 53
         }
55 54
     }
56
-    //! [Interesting]
55
+  //! [Interesting]
57 56
 
58
-    std::cout << "exiting application" << std::endl;
57
+  std::cout << "Existing..." << std::endl;
59 58
 
60
-    delete bar;
59
+  delete bar;
61 60
 
62
-    return 0;
61
+  return 0;
63 62
 }

+ 9
- 10
examples/c++/my9221-updown.cxx Целия файл

@@ -25,7 +25,7 @@
25 25
 #include <unistd.h>
26 26
 #include <iostream>
27 27
 #include <signal.h>
28
-#include "my9221.h"
28
+#include "groveledbar.h"
29 29
 
30 30
 using namespace std;
31 31
 
@@ -44,26 +44,25 @@ int main ()
44 44
 
45 45
 //! [Interesting] 
46 46
 
47
-  // Instantiate a MY9221, we use D2 for the data, and D3 for the
48
-  // data clock.  This was tested with a Grove LED bar.
49
-
50
-  upm::MY9221* bar = new upm::MY9221(2, 3);
47
+  // Instantiate a GroveLEDBar, we use D8 for the data, and D9 for the
48
+  // clock.  This was tested with a Grove LED bar.
49
+  upm::GroveLEDBar* bar = new upm::GroveLEDBar(8, 9);
51 50
   
52 51
   while (shouldRun)
53 52
     {
54 53
       // count up from green to red
55
-      for (int i=1; i<=10; i++)
54
+      for (int i=0; i<=10; i++)
56 55
         {
57 56
           bar->setBarLevel(i, true);
58
-          usleep(50000);
57
+          usleep(100000);
59 58
         }
60 59
       sleep(1);
61 60
 
62 61
       // count down from red to green
63
-      for (int i=1; i<=10; i++)
62
+      for (int i=0; i<=10; i++)
64 63
         {
65 64
           bar->setBarLevel(i, false);
66
-          usleep(50000);
65
+          usleep(100000);
67 66
         }
68 67
       sleep(1);
69 68
     }
@@ -71,7 +70,7 @@ int main ()
71 70
 
72 71
   cout << "Exiting..." << endl;
73 72
   // turn off the LED's
74
-  bar->setBarLevel(0, true);
73
+  bar->setBarLevel(0);
75 74
 
76 75
   delete bar;
77 76
   return 0;

+ 3
- 3
src/my9221/CMakeLists.txt Целия файл

@@ -1,5 +1,5 @@
1 1
 set (libname "my9221")
2
-set (libdescription "upm ledbar")
3
-set (module_src ${libname}.cxx)
4
-set (module_h ${libname}.h)
2
+set (libdescription "upm my9221")
3
+set (module_src ${libname}.cxx groveledbar.cxx grovecircularled.cxx)
4
+set (module_h ${libname}.h groveledbar.h grovecircularled.h)
5 5
 upm_module_init()

+ 14
- 0
src/my9221/TODO Целия файл

@@ -0,0 +1,14 @@
1
+- split up bar and circular methods from my9221 into own libraries
2
+
3
+- add a getLED to match setLED
4
+
5
+- for bar, allow spec (via some method) to a specific bar
6
+
7
+- examples for my9221, keep existing ones for bar and circular
8
+
9
+- warning message if mmap gpio fails and more that 1 instance
10
+
11
+- make sure ctor throws exceptions on gpio setup errors, as well as
12
+  ensure at least one instance specified.
13
+
14
+- reg map of commandWord bits and provide accessor methods (set/get)

+ 94
- 0
src/my9221/grovecircularled.cxx Целия файл

@@ -0,0 +1,94 @@
1
+/*
2
+ * Author: Jon Trulson <jtrulson@ics.com>
3
+ * Copyright (c) 2016 Intel Corporation.
4
+ *
5
+ * These modules were rewritten, based on original work by:
6
+ *
7
+ * (original my9221/groveledbar driver)
8
+ * Author: Yevgeniy Kiveisha <yevgeniy.kiveisha@intel.com>
9
+ * Copyright (c) 2014 Intel Corporation.
10
+ *
11
+ * (grovecircularled driver)
12
+ * Author: Jun Kato and Yevgeniy Kiveisha <yevgeniy.kiveisha@intel.com>
13
+ * Contributions: Jon Trulson <jtrulson@ics.com>
14
+ * Copyright (c) 2014 Intel Corporation.
15
+ *
16
+ * Permission is hereby granted, free of charge, to any person obtaining
17
+ * a copy of this software and associated documentation files (the
18
+ * "Software"), to deal in the Software without restriction, including
19
+ * without limitation the rights to use, copy, modify, merge, publish,
20
+ * distribute, sublicense, and/or sell copies of the Software, and to
21
+ * permit persons to whom the Software is furnished to do so, subject to
22
+ * the following conditions:
23
+ *
24
+ * The above copyright notice and this permission notice shall be
25
+ * included in all copies or substantial portions of the Software.
26
+ *
27
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
28
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
29
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
30
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
31
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
32
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
33
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
34
+ */
35
+
36
+#include <iostream>
37
+#include <string>
38
+#include <stdexcept>
39
+#include <unistd.h>
40
+#include <stdlib.h>
41
+
42
+#include "grovecircularled.h"
43
+
44
+using namespace upm;
45
+using namespace std;
46
+
47
+GroveCircularLED::GroveCircularLED (uint8_t dataPin, uint8_t clockPin)
48
+  : MY9221(dataPin, clockPin, 2)
49
+{
50
+  // auto refresh by default
51
+  setAutoRefresh(true);
52
+  clearAll();
53
+}
54
+
55
+GroveCircularLED::~GroveCircularLED()
56
+{
57
+}
58
+
59
+void GroveCircularLED::setSpinner(uint8_t position)
60
+{
61
+  if (position > 23)
62
+    position = 23;
63
+
64
+  for (uint8_t i=0; i<(LEDS_PER_INSTANCE * m_instances); i++)
65
+    m_bitStates[i] = (i == position) ? m_highIntensity : m_lowIntensity;
66
+
67
+  if (m_autoRefresh)
68
+    refresh();
69
+
70
+  return;
71
+}
72
+
73
+void GroveCircularLED::setLevel(uint8_t level, bool direction)
74
+{
75
+  if (level > 23)
76
+    level = 23;
77
+
78
+  if (!direction)
79
+    {
80
+      for (int i=0; i<(LEDS_PER_INSTANCE * m_instances); i++)
81
+        m_bitStates[i] = (i < level) ? m_highIntensity : m_lowIntensity;
82
+    }
83
+  else
84
+    {
85
+      for (int i=0; i<(LEDS_PER_INSTANCE * m_instances); i++)
86
+        m_bitStates[i] = (((LEDS_PER_INSTANCE * m_instances) - i) <= level)
87
+          ? m_highIntensity : m_lowIntensity;
88
+    }
89
+
90
+  if (m_autoRefresh)
91
+    refresh();
92
+
93
+  return;
94
+}

+ 96
- 0
src/my9221/grovecircularled.h Целия файл

@@ -0,0 +1,96 @@
1
+/*
2
+ * Author: Jon Trulson <jtrulson@ics.com>
3
+ * Copyright (c) 2016 Intel Corporation.
4
+ *
5
+ * These modules were rewritten, based on original work by:
6
+ *
7
+ * (original my9221/groveledbar)
8
+ * Author: Yevgeniy Kiveisha <yevgeniy.kiveisha@intel.com>
9
+ * Copyright (c) 2014 Intel Corporation.
10
+ *
11
+ * (grovecircularled)
12
+ * Author: Jun Kato and Yevgeniy Kiveisha <yevgeniy.kiveisha@intel.com>
13
+ * Contributions: Jon Trulson <jtrulson@ics.com>
14
+ * Copyright (c) 2014 Intel Corporation.
15
+ *
16
+ * Permission is hereby granted, free of charge, to any person obtaining
17
+ * a copy of this software and associated documentation files (the
18
+ * "Software"), to deal in the Software without restriction, including
19
+ * without limitation the rights to use, copy, modify, merge, publish,
20
+ * distribute, sublicense, and/or sell copies of the Software, and to
21
+ * permit persons to whom the Software is furnished to do so, subject to
22
+ * the following conditions:
23
+ *
24
+ * The above copyright notice and this permission notice shall be
25
+ * included in all copies or substantial portions of the Software.
26
+ *
27
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
28
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
29
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
30
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
31
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
32
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
33
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
34
+ */
35
+#pragma once
36
+
37
+#include <string>
38
+#include <mraa/common.hpp>
39
+#include <mraa/gpio.hpp>
40
+#include "my9221.h"
41
+
42
+namespace upm {
43
+
44
+  /**
45
+   * @library my9221
46
+   * @sensor grovecircularled
47
+   * @comname Grove Circular LED
48
+   * @type display
49
+   * @man seeed
50
+   * @web http://www.seeedstudio.com/wiki/Grove_-_Circular_LED
51
+   * @con gpio
52
+   *
53
+   * @brief API for the Grove Circular LED module
54
+   *
55
+   * This is a circular LED ring based on the MY9221 chip. It is often used
56
+   * with a rotary encoder and has 24 controllable LEDs.
57
+   *
58
+   * @image html grovecircularled.jpg
59
+   * @snippet grovecircularled.cxx Interesting
60
+   */
61
+
62
+  class GroveCircularLED : public MY9221 {
63
+  public:
64
+    /**
65
+     * Instantiates an GroveCircularLED object
66
+     *
67
+     * @param dataPin Data pin
68
+     * @param clockPin Clock pin
69
+     */
70
+    GroveCircularLED(uint8_t dataPin, uint8_t clockPin);
71
+
72
+    /**
73
+     * GroveCircularLED destructor
74
+     */
75
+    ~GroveCircularLED();
76
+
77
+    /**
78
+     * Sets the spinner (turns off all LEDs but selected one)
79
+     *
80
+     * @param position Selected position for the spinner (0-23)
81
+     */
82
+    void setSpinner(uint8_t position);
83
+
84
+    /**
85
+     * Sets the lighting status
86
+     *
87
+     * @param level Selected level for the circular LED (0-23)
88
+     * @param direction Up or down; up is true and default
89
+     */
90
+    void setLevel(uint8_t level, bool direction=true);
91
+
92
+  protected:
93
+  private:
94
+  };
95
+
96
+}

+ 88
- 0
src/my9221/groveledbar.cxx Целия файл

@@ -0,0 +1,88 @@
1
+/*
2
+ * Author: Jon Trulson <jtrulson@ics.com>
3
+ * Copyright (c) 2016 Intel Corporation.
4
+ *
5
+ * These modules were rewritten, based on original work by:
6
+ *
7
+ * (original my9221/groveledbar driver)
8
+ * Author: Yevgeniy Kiveisha <yevgeniy.kiveisha@intel.com>
9
+ * Copyright (c) 2014 Intel Corporation.
10
+ *
11
+ * (grovecircularled driver)
12
+ * Author: Jun Kato and Yevgeniy Kiveisha <yevgeniy.kiveisha@intel.com>
13
+ * Contributions: Jon Trulson <jtrulson@ics.com>
14
+ * Copyright (c) 2014 Intel Corporation.
15
+ *
16
+ * Permission is hereby granted, free of charge, to any person obtaining
17
+ * a copy of this software and associated documentation files (the
18
+ * "Software"), to deal in the Software without restriction, including
19
+ * without limitation the rights to use, copy, modify, merge, publish,
20
+ * distribute, sublicense, and/or sell copies of the Software, and to
21
+ * permit persons to whom the Software is furnished to do so, subject to
22
+ * the following conditions:
23
+ *
24
+ * The above copyright notice and this permission notice shall be
25
+ * included in all copies or substantial portions of the Software.
26
+ *
27
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
28
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
29
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
30
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
31
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
32
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
33
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
34
+ */
35
+
36
+#include <iostream>
37
+#include <string>
38
+#include <stdexcept>
39
+#include <unistd.h>
40
+#include <stdlib.h>
41
+
42
+#include "groveledbar.h"
43
+
44
+using namespace upm;
45
+using namespace std;
46
+
47
+GroveLEDBar::GroveLEDBar (uint8_t dataPin, uint8_t clockPin, int instances)
48
+  : MY9221(dataPin, clockPin, instances)
49
+{
50
+  // auto refresh by default
51
+  setAutoRefresh(true);
52
+  clearAll();
53
+}
54
+
55
+GroveLEDBar::~GroveLEDBar()
56
+{
57
+}
58
+
59
+void GroveLEDBar::setBarLevel(uint8_t level, bool greenToRed, int barNumber)
60
+{
61
+  if (level > 10)
62
+    level = 10;
63
+
64
+  if (barNumber >= m_instances)
65
+    barNumber = m_instances - 1;
66
+
67
+  int start = barNumber * LEDS_PER_INSTANCE;
68
+  int end = start + LEDS_PER_INSTANCE;
69
+
70
+  if (!greenToRed)
71
+    {
72
+      for (int i=start; i<end; i++)
73
+        m_bitStates[i] = (i < (level + start)) ?
74
+          m_highIntensity : m_lowIntensity;
75
+    }
76
+  else
77
+    {
78
+      for (int i=start; i<end; i++)
79
+        m_bitStates[i] = ( ((start + LEDS_PER_INSTANCE) - i) <=
80
+                           (level + 2 + start)) ?
81
+                           m_highIntensity : m_lowIntensity;
82
+    }
83
+
84
+  if (m_autoRefresh)
85
+    refresh();
86
+
87
+  return;
88
+}

+ 99
- 0
src/my9221/groveledbar.h Целия файл

@@ -0,0 +1,99 @@
1
+/*
2
+ * Author: Jon Trulson <jtrulson@ics.com>
3
+ * Copyright (c) 2016 Intel Corporation.
4
+ *
5
+ * These modules were rewritten, based on original work by:
6
+ *
7
+ * (original my9221/groveledbar)
8
+ * Author: Yevgeniy Kiveisha <yevgeniy.kiveisha@intel.com>
9
+ * Copyright (c) 2014 Intel Corporation.
10
+ *
11
+ * (grovecircularled)
12
+ * Author: Jun Kato and Yevgeniy Kiveisha <yevgeniy.kiveisha@intel.com>
13
+ * Contributions: Jon Trulson <jtrulson@ics.com>
14
+ * Copyright (c) 2014 Intel Corporation.
15
+ *
16
+ * Permission is hereby granted, free of charge, to any person obtaining
17
+ * a copy of this software and associated documentation files (the
18
+ * "Software"), to deal in the Software without restriction, including
19
+ * without limitation the rights to use, copy, modify, merge, publish,
20
+ * distribute, sublicense, and/or sell copies of the Software, and to
21
+ * permit persons to whom the Software is furnished to do so, subject to
22
+ * the following conditions:
23
+ *
24
+ * The above copyright notice and this permission notice shall be
25
+ * included in all copies or substantial portions of the Software.
26
+ *
27
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
28
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
29
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
30
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
31
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
32
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
33
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
34
+ */
35
+#pragma once
36
+
37
+#include <string>
38
+#include <mraa/common.hpp>
39
+#include <mraa/gpio.hpp>
40
+
41
+#include "my9221.h"
42
+
43
+namespace upm {
44
+
45
+  /**
46
+   * @library my9221
47
+   * @sensor groveledbar
48
+   * @comname Grove LED Bar
49
+   * @altname MY9221 LED Bar
50
+   * @type display
51
+   * @man seeed
52
+   * @web http://www.seeedstudio.com/wiki/Grove_-_LED_Bar
53
+   * @con gpio
54
+   * @kit eak
55
+   *
56
+   * @brief API for Grove LED Bars base on the MY9221
57
+   *
58
+   * This is a 10-segment LED bar, with 8 green segments, 1 yellow
59
+   * segment, and one red segment.  They can be daisy chained together
60
+   * so that this module can control multiple LED bars.
61
+   *
62
+   * @image html my9221.jpg
63
+   * @snippet groveledbar.cxx Interesting
64
+   */
65
+
66
+  class GroveLEDBar : public MY9221 {
67
+  public:
68
+
69
+    /**
70
+     * Instantiates an GroveLEDBar object
71
+     *
72
+     * @param dataPin Data pin
73
+     * @param clockPin Clock pin
74
+     * @param instances Number of daisy-chained Grove LED Bars, default 1
75
+     */
76
+    GroveLEDBar(uint8_t dataPin, uint8_t clockPin, int instances=1);
77
+
78
+    /**
79
+     * GroveLEDBar destructor
80
+     */
81
+    ~GroveLEDBar();
82
+
83
+    /**
84
+     * Sets the bar level
85
+     *
86
+     * @param level Selected level for the bar (0 - 10). 0 is off
87
+     * @param greenToRed true if you start the level on the first
88
+     * green LED, false otherwise
89
+     * @param barNumber If you have multiple LED bars chained
90
+     * together, this argument selects a specific bar starting at 0.
91
+     * The default is 0.
92
+     */
93
+    void setBarLevel(uint8_t level, bool greenToRed=true, int barNumber=0);
94
+
95
+  protected:
96
+  private:
97
+  };
98
+
99
+}

+ 141
- 56
src/my9221/my9221.cxx Целия файл

@@ -1,7 +1,18 @@
1 1
 /*
2
+ * Author: Jon Trulson <jtrulson@ics.com>
3
+ * Copyright (c) 2016 Intel Corporation.
4
+ *
5
+ * These modules were rewritten, based on original work by:
6
+ *
7
+ * (original my9221/groveledbar driver)
2 8
  * Author: Yevgeniy Kiveisha <yevgeniy.kiveisha@intel.com>
3 9
  * Copyright (c) 2014 Intel Corporation.
4 10
  *
11
+ * (grovecircularled driver)
12
+ * Author: Jun Kato and Yevgeniy Kiveisha <yevgeniy.kiveisha@intel.com>
13
+ * Contributions: Jon Trulson <jtrulson@ics.com>
14
+ * Copyright (c) 2014 Intel Corporation.
15
+ *
5 16
  * Permission is hereby granted, free of charge, to any person obtaining
6 17
  * a copy of this software and associated documentation files (the
7 18
  * "Software"), to deal in the Software without restriction, including
@@ -31,76 +42,150 @@
31 42
 #include "my9221.h"
32 43
 
33 44
 using namespace upm;
45
+using namespace std;
34 46
 
35
-MY9221::MY9221 (uint8_t di, uint8_t dcki)
36
-                    : m_clkPinCtx(dcki), m_dataPinCtx(di) {
37
-    mraa::Result error = mraa::SUCCESS;
38
-
39
-    // set direction (out)
40
-    error = m_clkPinCtx.dir(mraa::DIR_OUT);
41
-    if (error != mraa::SUCCESS) {
42
-        mraa::printError(error);
47
+MY9221::MY9221 (uint8_t dataPin, uint8_t clockPin, int instances)
48
+  : m_gpioData(dataPin), m_gpioClk(clockPin), m_bitStates(0)
49
+{
50
+  if (instances < 1)
51
+    {
52
+      throw std::out_of_range(std::string(__FUNCTION__) +
53
+                              ": instances must be at least 1");
43 54
     }
44 55
 
45
-    // set direction (out)
46
-    error = m_dataPinCtx.dir(mraa::DIR_OUT);
47
-    if (error != mraa::SUCCESS) {
48
-        mraa::printError(error);
49
-    }
56
+  // set directions
57
+  m_gpioClk.dir(mraa::DIR_OUT);
58
+  m_gpioData.dir(mraa::DIR_OUT);
59
+  
60
+  // we warn if these fail, since it may not be possible to handle
61
+  // more than one instance
62
+
63
+  if (m_gpioClk.useMmap(true) != mraa::SUCCESS)
64
+    cerr << __FUNCTION__
65
+         << ": Warning: mmap of Clk pin failed, correct operation "
66
+         << "may be affected."
67
+         << endl;
68
+
69
+  if (m_gpioData.useMmap(true) != mraa::SUCCESS)
70
+    cerr << __FUNCTION__
71
+         << ": Warning: mmap of Data pin failed, correct operation "
72
+         << "may be affected."
73
+         << endl;
74
+
75
+  setLowIntensityValue(0x00);   // full off
76
+  setHighIntensityValue(0xff);  // full brightness
77
+
78
+  m_commandWord = 0x0000;       // all defaults
79
+  m_instances = instances;
80
+
81
+  m_bitStates = new uint16_t[instances * LEDS_PER_INSTANCE];
82
+
83
+  setAutoRefresh(true);
84
+  clearAll();
50 85
 }
51 86
 
52
-mraa::Result
53
-MY9221::setBarLevel (uint8_t level, bool direction) {
54
-    if (level > 10) {
55
-        return mraa::ERROR_INVALID_PARAMETER;
56
-    }
87
+MY9221::~MY9221()
88
+{
89
+  clearAll();
57 90
 
58
-    send16bitBlock (CMDMODE);
59
-    if (direction) {
60
-        level += 3;
61
-        for(uint8_t block_idx = 12; block_idx > 0; block_idx--) {
62
-            uint32_t state = (block_idx < level) ? BIT_HIGH : BIT_LOW;
63
-            send16bitBlock (state);
64
-        }
65
-    } else {
66
-        for(uint8_t block_idx = 0; block_idx < 12; block_idx++) {
67
-            uint32_t state = (block_idx < level) ? BIT_HIGH : BIT_LOW;
68
-            send16bitBlock (state);
91
+  if (!m_autoRefresh)
92
+    refresh();
93
+
94
+  delete m_bitStates;
95
+}
96
+
97
+void MY9221::setLED(int led, bool on)
98
+{
99
+  int maxLed = (LEDS_PER_INSTANCE * m_instances) - 1;
100
+
101
+  if (led > maxLed)
102
+    led = maxLed;
103
+  if (led < 0)
104
+    led = 0;
105
+
106
+  m_bitStates[led] = (on) ? m_highIntensity : m_lowIntensity;
107
+
108
+  if (m_autoRefresh)
109
+    refresh();
110
+}
111
+
112
+void MY9221::setLowIntensityValue(int intensity)
113
+{
114
+  m_lowIntensity = (intensity & 0xff);
115
+}
116
+
117
+void MY9221::setHighIntensityValue(int intensity)
118
+{
119
+  m_highIntensity = (intensity & 0xff);
120
+}
121
+
122
+void MY9221::setAll()
123
+{
124
+  for (int i=0; i<(m_instances * LEDS_PER_INSTANCE); i++)
125
+    m_bitStates[i] = m_highIntensity;
126
+
127
+  if (m_autoRefresh)
128
+    refresh();
129
+}
130
+
131
+void MY9221::clearAll()
132
+{
133
+  for (int i=0; i<(m_instances * LEDS_PER_INSTANCE); i++)
134
+    m_bitStates[i] = m_lowIntensity;
135
+
136
+  if (m_autoRefresh)
137
+    refresh();
138
+}
139
+
140
+void MY9221::refresh()
141
+{
142
+  for (int i=0; i<(m_instances * LEDS_PER_INSTANCE); i++)
143
+    {
144
+      if (i % 12 == 0)
145
+        {
146
+          send16bitBlock(m_commandWord);
69 147
         }
148
+      send16bitBlock(m_bitStates[i]);
70 149
     }
71
-    return lockData ();
150
+
151
+  lockData();
72 152
 }
73 153
 
74
-mraa::Result
75
-MY9221::lockData () {
76
-    mraa::Result error = mraa::SUCCESS;
77
-    error = m_dataPinCtx.write(LOW);
78
-    usleep(100);
154
+void MY9221::lockData()
155
+{
156
+  m_gpioData.write(0);
157
+  usleep(220);
79 158
 
80
-    for(int idx = 0; idx < 4; idx++) {
81
-        error = m_dataPinCtx.write(HIGH);
82
-        error = m_dataPinCtx.write(LOW);
159
+  for(int idx = 0; idx < 4; idx++)
160
+    {
161
+      m_gpioData.write(1);
162
+      m_gpioData.write(0);
83 163
     }
84
-    return error;
85
-}
86 164
 
87
-mraa::Result
88
-MY9221::send16bitBlock (short data) {
89
-    mraa::Result error = mraa::SUCCESS;
90
-    for (uint8_t bit_idx = 0; bit_idx < MAX_BIT_PER_BLOCK; bit_idx++) {
91
-        uint32_t state = (data & 0x8000) ? HIGH : LOW;
92
-        error = m_dataPinCtx.write(state);
93
-        state = m_clkPinCtx.read();
94
-
95
-        if (state) {
96
-            state = LOW;
97
-        } else {
98
-            state = HIGH;
99
-        }
165
+  // in reality, we only need > 200ns + (m_instances * 10ns), so the
166
+  // following should be good for up to m_instances < 80), if the
167
+  // datasheet is to be believed :)
168
+  usleep(1);
169
+
170
+  return;
171
+}
100 172
 
101
-        error = m_clkPinCtx.write(state);
173
+void MY9221::send16bitBlock(uint16_t data)
174
+{
175
+  for (uint8_t bit_idx = 0; bit_idx < 16; bit_idx++)
176
+    {
177
+      uint32_t state = (data & 0x8000) ? 1 : 0;
178
+      m_gpioData.write(state);
179
+      state = m_gpioClk.read();
102 180
 
103
-        data <<= 1;
181
+      if (state)
182
+        state = 0;
183
+      else
184
+        state = 1;
185
+      
186
+      m_gpioClk.write(state);
187
+      
188
+      data <<= 1;
104 189
     }
105
-    return error;
190
+  return;
106 191
 }

+ 118
- 66
src/my9221/my9221.h Целия файл

@@ -1,7 +1,18 @@
1 1
 /*
2
+ * Author: Jon Trulson <jtrulson@ics.com>
3
+ * Copyright (c) 2016 Intel Corporation.
4
+ *
5
+ * These modules were rewritten, based on original work by:
6
+ *
7
+ * (original my9221/groveledbar)
2 8
  * Author: Yevgeniy Kiveisha <yevgeniy.kiveisha@intel.com>
3 9
  * Copyright (c) 2014 Intel Corporation.
4 10
  *
11
+ * (grovecircularled)
12
+ * Author: Jun Kato and Yevgeniy Kiveisha <yevgeniy.kiveisha@intel.com>
13
+ * Contributions: Jon Trulson <jtrulson@ics.com>
14
+ * Copyright (c) 2014 Intel Corporation.
15
+ *
5 16
  * Permission is hereby granted, free of charge, to any person obtaining
6 17
  * a copy of this software and associated documentation files (the
7 18
  * "Software"), to deal in the Software without restriction, including
@@ -24,77 +35,118 @@
24 35
 #pragma once
25 36
 
26 37
 #include <string>
27
-#include <mraa/aio.hpp>
28 38
 #include <mraa/common.hpp>
29
-
30 39
 #include <mraa/gpio.hpp>
31 40
 
32
-#define MAX_BIT_PER_BLOCK     16
33
-#define CMDMODE               0x0000
34
-#define BIT_HIGH              0x00ff
35
-#define BIT_LOW               0x0000
41
+namespace upm {
36 42
 
37
-#define HIGH                  1
38
-#define LOW                   0
43
+  /**
44
+   * @brief MY9221 LED Controller library
45
+   * @defgroup my9221 libupm-my9221
46
+   * @ingroup seeed display gpio eak
47
+   */
48
+  class MY9221 {
49
+  public:
39 50
 
40
-namespace upm {
51
+    // 12 LED channels per chip (instance)
52
+    static const int LEDS_PER_INSTANCE = 12;
41 53
 
42
-/**
43
- * @brief MY9221 LED Bar library
44
- * @defgroup my9221 libupm-my9221
45
- * @ingroup seeed display gpio eak
46
- */
47
-/**
48
- * @library my9221
49
- * @sensor my9221
50
- * @comname Grove LED Bar
51
- * @altname MY9221 LED Bar
52
- * @type display
53
- * @man seeed
54
- * @web http://www.seeedstudio.com/wiki/Grove_-_LED_Bar
55
- * @con gpio
56
- * @kit eak
57
- *
58
- * @brief API for MY9221-based LED Bars
59
- *
60
- * This module defines the MY9221 interface for libmy9221
61
- *
62
- * @image html my9221.jpg
63
- * @snippet my9221-ledbar.cxx Interesting
64
- * @snippet my9221-updown.cxx Interesting
65
- */
66
-class MY9221 {
67
-    public:
68
-         /**
69
-         * Instantiates an MY9221 object
70
-         *
71
-         * @param di Data pin
72
-         * @param dcki Clock pin
73
-         */
74
-        MY9221 (uint8_t di, uint8_t dcki);
75
-
76
-        /**
77
-         * Sets the bar level 
78
-         *
79
-         * @param level Selected level for the bar (1 - 10)
80
-         * @param direction Up or down; up is true and default
81
-         */
82
-        mraa::Result setBarLevel (uint8_t level, bool direction=true);
83
-
84
-        /**
85
-         * Returns the name of the component
86
-         */
87
-        std::string name()
88
-        {
89
-            return m_name;
90
-        }
91
-    private:
92
-        mraa::Result lockData ();
93
-        mraa::Result send16bitBlock (short data);
94
-
95
-        std::string m_name;
96
-        mraa::Gpio m_clkPinCtx;
97
-        mraa::Gpio m_dataPinCtx;
98
-};
54
+    /**
55
+     * Instantiates an MY9221 object
56
+     *
57
+     * @param dataPin Data pin
58
+     * @param clockPin Clock pin
59
+     * @param instances Number of daisy-chained my9221s, default 1
60
+     */
61
+    MY9221(uint8_t dataPin, uint8_t clockPin, int instances=1);
62
+
63
+    /**
64
+     * MY9221 destructor
65
+     */
66
+    ~MY9221();
67
+
68
+    /**
69
+     * Enable or disable auto refresh.  When auto refresh is enabled,
70
+     * update the LED display as soon as the internal state changes.
71
+     * When false, the display(s) will not be updated until the
72
+     * refresh() method is called.
73
+     *
74
+     * @param enable true to enable auto refresh, false otherwise
75
+     */
76
+    void setAutoRefresh(bool enable)
77
+    {
78
+      m_autoRefresh = enable;
79
+    }
80
+
81
+    /**
82
+     * Set an LED to a specific on (high intensity) or off (low
83
+     * intensity) value.
84
+     *
85
+     * @param led The LED whose state you wish to change
86
+     * @param on true to turn on the LED, false to turn the LED off
87
+     */
88
+    void setLED(int led, bool on);
89
+
90
+    /**
91
+     * Set the greyscale intensity of an LED in the OFF state.  The
92
+     * intensity is a value from 0 (fully off) to 255 (fully on).
93
+     * This will take effect on any future LED set or clear
94
+     * operations.
95
+     *
96
+     * @param intensity a value from 0 (fully off) to 255 (fully on)
97
+     */
98
+    void setLowIntensityValue(int intensity);
99
+
100
+    /**
101
+     * Set the greyscale intensity of an LED in the ON state.  The
102
+     * intensity is a value from 0 (fully off) to 255 (fully on).
103
+     * This will take effect on any future LED set or clear
104
+     * operations.
105
+     *
106
+     * @param intensity a value from 0 (fully off) to 255 (fully on)
107
+     */
108
+    void setHighIntensityValue(int intensity);
109
+
110
+    /**
111
+     * Set all of the LEDS to the ON (high intensity value) state.
112
+     */
113
+    void setAll();
114
+
115
+    /**
116
+     * Set all of the LEDS to the OFF (low intensity value) state.
117
+     */
118
+    void clearAll();
119
+
120
+    /**
121
+     * Set the LED states to match the internal stored states.  This
122
+     * is useful when auto refresh (setAutoRefresh()) is false to
123
+     * update the display.
124
+     */
125
+    void refresh();
126
+
127
+  protected:
128
+    virtual void lockData();
129
+    virtual void send16bitBlock(uint16_t data);
130
+
131
+    bool m_autoRefresh;
132
+    // we're only doing 8-bit greyscale, so the high order bits are
133
+    // always 0
134
+    uint16_t m_lowIntensity;
135
+    uint16_t m_highIntensity;
136
+
137
+    unsigned int m_instances;
138
+
139
+    // an array of uint16_t's representing our bit states (on/off)
140
+    // intensities.  Only the low 8 bits are used, but in the future
141
+    // 16bit support can work here as well.
142
+    uint16_t *m_bitStates;
143
+
144
+    uint16_t m_commandWord;
145
+
146
+    mraa::Gpio m_gpioClk;
147
+    mraa::Gpio m_gpioData;
148
+
149
+  private:
150
+  };
99 151
 
100 152
 }