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