1 /*
2  * Author: Yevgeniy Kiveisha <yevgeniy.kiveisha@intel.com>
3  * Copyright (c) 2014 Intel Corporation.
4  *
5  * Credits to Seeed Studeo.
6  * Based on Seeed Studeo code example,
7  * http://www.seeedstudio.com/wiki/index.php?title=Twig_-_I2C_Color_Sensor_v0.9b.
8  *
9  * Permission is hereby granted, free of charge, to any person obtaining
10  * a copy of this software and associated documentation files (the
11  * "Software"), to deal in the Software without restriction, including
12  * without limitation the rights to use, copy, modify, merge, publish,
13  * distribute, sublicense, and/or sell copies of the Software, and to
14  * permit persons to whom the Software is furnished to do so, subject to
15  * the following conditions:
16  *
17  * The above copyright notice and this permission notice shall be
18  * included in all copies or substantial portions of the Software.
19  *
20  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27  */
28 
29 #include <iostream>
30 #include <unistd.h>
31 #include <stdlib.h>
32 #include <stdexcept>
33 
34 #include "tcs3414cs.h"
35 
36 using namespace upm;
37 
TCS3414CS()38 TCS3414CS::TCS3414CS () : m_i2Ctx(0) {
39     m_name = "TCS3414CS";
40 
41     mraa::Result ret = m_i2Ctx.address(ADDR);
42     if (ret != mraa::SUCCESS) {
43         throw std::invalid_argument(std::string(__FUNCTION__) +
44                                     ": m_i2Ctx.address() failed");
45     }
46 
47     // Set timing register
48     i2cWriteReg (REG_TIMING, INTEG_MODE_FREE);
49     usleep (100000);
50 
51     // Set interrupt source register
52     i2cWriteReg (REG_INT_SOURCE, INT_SOURCE_GREEN);
53     usleep (100000);
54 
55     // Set interrupt control register
56     i2cWriteReg (REG_INT, INTR_LEVEL | INTR_PERSIST_EVERY);
57     usleep (100000);
58 
59     // Set gain
60     i2cWriteReg (REG_GAIN, GAIN_1 | PRESCALER_4);
61     usleep (100000);
62 
63     // Enable ADC
64     i2cWriteReg (REG_CTL, CTL_DAT_INIITIATE);
65     usleep (100000);
66 }
67 
68 void
readRGB(tcs3414sc_rgb_t * rgb)69 TCS3414CS::readRGB (tcs3414sc_rgb_t * rgb) {
70     uint8_t buffer[8];
71 
72     // We need 7 bytes of data.
73     if (i2cReadReg_N (REG_BLOCK_READ, 8, buffer) > 7) {
74         rgb->g = buffer[1] * 256 + buffer[0];
75         rgb->r = buffer[3] * 256 + buffer[2];
76         rgb->b = buffer[5] * 256 + buffer[4];
77         rgb->clr = buffer[7] * 256 + buffer[6];
78     }
79 }
80 
81 void
clearInterrupt()82 TCS3414CS::clearInterrupt () {
83     mraa::Result error = mraa::SUCCESS;
84 
85     error = m_i2Ctx.address (ADDR);
86     error = m_i2Ctx.writeByte (CLR_INT);
87 
88     if (error != mraa::SUCCESS) {
89         throw std::runtime_error(std::string(__FUNCTION__) +
90                                  ": Couldn't clear interrupt");
91     }
92 }
93 
94 /*
95  * **************
96  *  private area
97  * **************
98  */
99 uint16_t
i2cReadReg_N(int reg,unsigned int len,uint8_t * buffer)100 TCS3414CS::i2cReadReg_N (int reg, unsigned int len, uint8_t * buffer) {
101     int readByte = 0;
102 
103     m_i2Ctx.address(ADDR);
104     m_i2Ctx.writeByte(reg);
105 
106     m_i2Ctx.address(ADDR);
107     readByte = m_i2Ctx.read(buffer, len);
108     return readByte;
109 }
110 
111 mraa::Result
i2cWriteReg_N(uint8_t reg,unsigned int len,uint8_t * buffer)112 TCS3414CS::i2cWriteReg_N (uint8_t reg, unsigned int len, uint8_t * buffer) {
113     mraa::Result error = mraa::SUCCESS;
114 
115     error = m_i2Ctx.address (ADDR);
116     error = m_i2Ctx.writeByte (reg);
117     error = m_i2Ctx.write (buffer, len);
118 
119     return error;
120 }
121 
122 mraa::Result
i2cWriteReg(uint8_t reg,uint8_t data)123 TCS3414CS::i2cWriteReg (uint8_t reg, uint8_t data) {
124     mraa::Result error = mraa::SUCCESS;
125 
126     error = m_i2Ctx.address (ADDR);
127     error = m_i2Ctx.writeByte (reg);
128     error = m_i2Ctx.writeByte (data);
129 
130     return error;
131 }
132