add functions to store boolean type sensor data
[apps/native/st-things-co2-meter.git] / src / adc-mcp3008.c
1 /*
2  * Copyright (c) 2017 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an AS IS BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include <stdlib.h>
18 #include <unistd.h>
19 #include <peripheral_io.h>
20 #include <tizen.h>
21 #include <system_info.h>
22 #include <string.h>
23 #include "log.h"
24
25
26 #define MCP3008_SPEED 3600000
27 #define MCP3008_BPW 8
28
29 #define MCP3008_TX_WORD1     0x01       /* 0b00000001 */
30 #define MCP3008_TX_CH0 0x80     /* 0b10000000 */
31 #define MCP3008_TX_CH1 0x90     /* 0b10010000 */
32 #define MCP3008_TX_CH2 0xA0     /* 0b10100000 */
33 #define MCP3008_TX_CH3 0xB0     /* 0b10110000 */
34 #define MCP3008_TX_CH4 0xC0     /* 0b11000000 */
35 #define MCP3008_TX_CH5 0xD0     /* 0b11010000 */
36 #define MCP3008_TX_CH6 0xE0     /* 0b11100000 */
37 #define MCP3008_TX_CH7 0xF0     /* 0b11110000 */
38 #define MCP3008_TX_WORD3     0x00       /* 0b00000000 */
39
40 #define MCP3008_RX_WORD1_MASK 0x00      /* 0b00000000 */
41 #define MCP3008_RX_WORD2_NULL_BIT_MASK 0x04     /* 0b00000100 */
42 #define MCP3008_RX_WORD2_MASK 0x03      /* 0b00000011 */
43 #define MCP3008_RX_WORD3_MASK 0xFF      /* 0b11111111 */
44 #define UINT10_VALIDATION_MASK 0x3FF
45
46 #define MODEL_NAME_KEY "http://tizen.org/system/model_name"
47 #define MODEL_NAME_RPI3 "rpi3"
48 #define MODEL_NAME_ARTIK "artik"
49
50 static peripheral_spi_h MCP3008_H = NULL;
51 static unsigned int ref_count = 0;
52
53 int adc_mcp3008_init(void)
54 {
55         int ret = 0;
56         int bus = -1;
57         char *model_name = NULL;
58
59         if (MCP3008_H) {
60                 _D("SPI device aleady initialized [ref_count : %u]", ref_count);
61                 ref_count++;
62                 return 0;
63         }
64
65         system_info_get_platform_string(MODEL_NAME_KEY, &model_name);
66         if (!model_name) {
67                 _E("fail to get model name");
68                 return -1;
69         }
70
71         if (!strcmp(model_name, MODEL_NAME_RPI3)) {
72                 bus = 0;
73         } else if (!strcmp(model_name, MODEL_NAME_ARTIK)) {
74                 bus = 2;
75         } else {
76                 _E("unknown model name : %s", model_name);
77                 free(model_name);
78                 return -1;
79         }
80         free(model_name);
81         model_name = NULL;
82
83         ret = peripheral_spi_open(bus, 0, &MCP3008_H);
84         if (PERIPHERAL_ERROR_NONE != ret) {
85                 _E("spi open failed :%s ", get_error_message(ret));
86                 return -1;
87         }
88
89         ret = peripheral_spi_set_mode(MCP3008_H, PERIPHERAL_SPI_MODE_0);
90         if (PERIPHERAL_ERROR_NONE != ret) {
91                 _E("peripheral_spi_set_mode failed :%s ", get_error_message(ret));
92                 goto error_after_open;
93         }
94         ret = peripheral_spi_set_bit_order(MCP3008_H, PERIPHERAL_SPI_BIT_ORDER_MSB);
95         if (PERIPHERAL_ERROR_NONE != ret) {
96                 _E("peripheral_spi_set_bit_order failed :%s ", get_error_message(ret));
97                 goto error_after_open;
98         }
99
100         ret = peripheral_spi_set_bits_per_word(MCP3008_H, MCP3008_BPW);
101         if (PERIPHERAL_ERROR_NONE != ret) {
102                 _E("peripheral_spi_set_bits_per_word failed :%s ", get_error_message(ret));
103                 goto error_after_open;
104         }
105
106         ret = peripheral_spi_set_frequency(MCP3008_H, MCP3008_SPEED);
107         if (PERIPHERAL_ERROR_NONE != ret) {
108                 _E("peripheral_spi_set_frequency failed :%s ", get_error_message(ret));
109                 goto error_after_open;
110         }
111
112         ref_count++;
113
114         return 0;
115
116 error_after_open:
117         peripheral_spi_close(MCP3008_H);
118         MCP3008_H = NULL;
119         return -1;
120 }
121
122
123 int adc_mcp3008_read(int ch_num, unsigned int *out_value)
124 {
125         unsigned char rx[3] = {0, };
126         unsigned char tx[3] = {0, };
127         unsigned char rx_w1 = 0;
128         unsigned char rx_w2 = 0;
129         unsigned char rx_w2_nb = 0;
130         unsigned char rx_w3 = 0;
131         unsigned short int result = 0;
132
133         retv_if(MCP3008_H == NULL, -1);
134         retv_if(out_value == NULL, -1);
135         retv_if((ch_num < 0 || ch_num > 7), -1);
136
137         tx[0] = MCP3008_TX_WORD1;
138         switch (ch_num) {
139         case 0:
140                 tx[1] = MCP3008_TX_CH0;
141                 break;
142         case 1:
143                 tx[1] = MCP3008_TX_CH1;
144                 break;
145         case 2:
146                 tx[1] = MCP3008_TX_CH2;
147                 break;
148         case 3:
149                 tx[1] = MCP3008_TX_CH3;
150                 break;
151         case 4:
152                 tx[1] = MCP3008_TX_CH4;
153                 break;
154         case 5:
155                 tx[1] = MCP3008_TX_CH5;
156                 break;
157         case 6:
158                 tx[1] = MCP3008_TX_CH6;
159                 break;
160         case 7:
161                 tx[1] = MCP3008_TX_CH7;
162                 break;
163         default:
164                 tx[1] = MCP3008_TX_CH0;
165                 break;
166         }
167         tx[2] = MCP3008_TX_WORD3;
168
169         peripheral_spi_transfer(MCP3008_H, tx, rx, 3);
170
171         rx_w1 = rx[0] & MCP3008_RX_WORD1_MASK;
172         retv_if(rx_w1 != 0, -1);
173
174         rx_w2_nb = rx[1] & MCP3008_RX_WORD2_NULL_BIT_MASK;
175         retv_if(rx_w2_nb != 0, -1);
176
177         rx_w2 = rx[1] & MCP3008_RX_WORD2_MASK;
178         rx_w3 = rx[2] & MCP3008_RX_WORD3_MASK;
179
180         result = ((rx_w2 << 8) | (rx_w3)) & UINT10_VALIDATION_MASK;
181
182         // _D("%hu", result);
183
184         *out_value = result;
185
186         return 0;
187 }
188
189 void adc_mcp3008_fini(void)
190 {
191         if (MCP3008_H)
192                 ref_count--;
193         else
194                 return;
195
196         if (ref_count == 0) {
197                 peripheral_spi_close(MCP3008_H);
198                 MCP3008_H = NULL;
199         }
200
201         return;
202 }
203