1765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang/*
2765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang * Author: Jun Kato and Yevgeniy Kiveisha <yevgeniy.kiveisha@intel.com>
3765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang * Contributions: Jon Trulson <jtrulson@ics.com>
4765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang * Copyright (c) 2015 Intel Corporation.
5765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang *
6765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang * This module is based on the my9221 driver
7765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang *
8765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang * Permission is hereby granted, free of charge, to any person obtaining
9765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang * a copy of this software and associated documentation files (the
10765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang * "Software"), to deal in the Software without restriction, including
11765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang * without limitation the rights to use, copy, modify, merge, publish,
12765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang * distribute, sublicense, and/or sell copies of the Software, and to
13765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang * permit persons to whom the Software is furnished to do so, subject to
14765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang * the following conditions:
15765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang *
16765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang * The above copyright notice and this permission notice shall be
17765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang * included in all copies or substantial portions of the Software.
18765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang *
19765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
20765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
22765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
23765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
24765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
25765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang */
27765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
28765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang#include <iostream>
29765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang#include <string>
30765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang#include <stdexcept>
31765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang#include <unistd.h>
32765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang#include <stdlib.h>
33765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
34765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang#include "grovecircularled.h"
35765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
36765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhangusing namespace upm;
37765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
38765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun ZhangGroveCircularLED::GroveCircularLED (uint8_t di, uint8_t dcki)
39765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang									: m_clkPinCtx(dcki),
40765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang									  m_dataPinCtx(di) {
41765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  mraa::Result error = mraa::SUCCESS;
42765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
43765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  m_clkPinCtx.useMmap(true);
44765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  m_dataPinCtx.useMmap(true);
45765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
46765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  // set direction (out)
47765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  error = m_clkPinCtx.dir(mraa::DIR_OUT);
48765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  if (error != mraa::SUCCESS) {
49765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang    printError(error);
50765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  }
51765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang}
52765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
53765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhangmraa::Result
54765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun ZhangGroveCircularLED::setSpinner (uint8_t position) {
55765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  if (position < 0 || position >= 24) {
56765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang    return mraa::ERROR_INVALID_PARAMETER;
57765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  }
58765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  for(uint8_t block_idx = 0; block_idx < 24; block_idx++) {
59765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang    if (block_idx % 12 == 0) {
60765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang        send16bitBlock (CMDMODE);
61765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang    }
62765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang    uint32_t state = (block_idx == position) ? BIT_HIGH : BIT_LOW;
63765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang    send16bitBlock (state);
64765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  }
65765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  return lockData ();
66765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang}
67765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
68765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhangmraa::Result
69765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun ZhangGroveCircularLED::setLevel (uint8_t level, bool direction) {
70765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  if (level < 0 || level > 24) {
71765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang    return mraa::ERROR_INVALID_PARAMETER;
72765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  }
73765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  if (direction) {
74765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang    for(uint8_t block_idx = 24; block_idx > 0; block_idx--) {
75765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang      if (block_idx % 12 == 0) {
76765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang        send16bitBlock (CMDMODE);
77765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang      }
78765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang      uint32_t state = (block_idx <= level) ? BIT_HIGH : BIT_LOW;
79765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang      send16bitBlock (state);
80765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang    }
81765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  } else {
82765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang    for(uint8_t block_idx = 0; block_idx < 24; block_idx++) {
83765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang      if (block_idx % 12 == 0) {
84765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang        send16bitBlock (CMDMODE);
85765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang      }
86765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang      uint32_t state = (block_idx <= level - 1) ? BIT_HIGH : BIT_LOW;
87765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang      send16bitBlock (state);
88765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang    }
89765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  }
90765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  return lockData ();
91765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang}
92765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
93765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhangmraa::Result
94765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun ZhangGroveCircularLED::setStatus (bool status[24]) {
95765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  for(uint8_t block_idx = 0; block_idx < 24; block_idx++) {
96765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang    if (block_idx % 12 == 0) {
97765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang      send16bitBlock (CMDMODE);
98765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang    }
99765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang    send16bitBlock (status[block_idx] ? BIT_HIGH : BIT_LOW);
100765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  }
101765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  return lockData ();
102765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang}
103765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
104765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhangmraa::Result
105765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun ZhangGroveCircularLED::lockData () {
106765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang    mraa::Result error = mraa::SUCCESS;
107765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  error = m_dataPinCtx.write (LOW);
108765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  usleep(10);
109765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
110765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  for(int idx = 0; idx < 4; idx++) {
111765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang    error = m_dataPinCtx.write(HIGH);
112765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang    error = m_dataPinCtx.write(LOW);
113765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  }
114765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  return error;
115765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang}
116765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
117765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhangmraa::Result
118765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun ZhangGroveCircularLED::send16bitBlock (short data) {
119765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang    mraa::Result error = mraa::SUCCESS;
120765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang    for (uint8_t bit_idx = 0; bit_idx < MAX_BIT_PER_BLOCK; bit_idx++) {
121765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang        uint32_t state = (data & 0x8000) ? HIGH : LOW;
122765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang        error = m_dataPinCtx.write (state);
123765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang        state = m_clkPinCtx.read ();
124765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
125765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang        if (state) {
126765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang            state = LOW;
127765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang        } else {
128765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang            state = HIGH;
129765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang        }
130765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
131765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang        error = m_clkPinCtx.write (state);
132765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang
133765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang        data <<= 1;
134765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang    }
135765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang  return error;
136765adb95dc941c32690d6c43bc08b9d07d197fcbJianxun Zhang}
137