Firmware SDK
 All Data Structures Functions Variables Typedefs Enumerations Enumerator Groups Pages
bc_tmp112.c
1 #include <bc_tmp112.h>
2 
3 #define _BC_TMP112_DELAY_RUN 50
4 #define _BC_TMP112_DELAY_INITIALIZATION 50
5 #define _BC_TMP112_DELAY_MEASUREMENT 50
6 
7 static void _bc_tmp112_task_interval(void *param);
8 
9 static void _bc_tmp112_task_measure(void *param);
10 
11 void bc_tmp112_init(bc_tmp112_t *self, bc_i2c_channel_t i2c_channel, uint8_t i2c_address)
12 {
13  memset(self, 0, sizeof(*self));
14 
15  self->_i2c_channel = i2c_channel;
16  self->_i2c_address = i2c_address;
17 
18  self->_task_id_interval = bc_scheduler_register(_bc_tmp112_task_interval, self, BC_TICK_INFINITY);
19  self->_task_id_measure = bc_scheduler_register(_bc_tmp112_task_measure, self, _BC_TMP112_DELAY_RUN);
20 
21  self->_tick_ready = _BC_TMP112_DELAY_RUN;
22 
23  bc_i2c_init(self->_i2c_channel, BC_I2C_SPEED_400_KHZ);
24 }
25 
27 {
28  bc_i2c_memory_write_16b(self->_i2c_channel, self->_i2c_address, 0x01, 0x0180);
29 
30  bc_scheduler_unregister(self->_task_id_interval);
31 
32  bc_scheduler_unregister(self->_task_id_measure);
33 }
34 
35 void bc_tmp112_set_event_handler(bc_tmp112_t *self, void (*event_handler)(bc_tmp112_t *, bc_tmp112_event_t, void *), void *event_param)
36 {
37  self->_event_handler = event_handler;
38  self->_event_param = event_param;
39 }
40 
42 {
43  self->_update_interval = interval;
44 
45  if (self->_update_interval == BC_TICK_INFINITY)
46  {
47  bc_scheduler_plan_absolute(self->_task_id_interval, BC_TICK_INFINITY);
48  }
49  else
50  {
51  bc_scheduler_plan_relative(self->_task_id_interval, self->_update_interval);
52 
53  bc_tmp112_measure(self);
54  }
55 }
56 
58 {
59  if (self->_measurement_active)
60  {
61  return false;
62  }
63 
64  self->_measurement_active = true;
65 
66  bc_scheduler_plan_absolute(self->_task_id_measure, self->_tick_ready);
67 
68  return true;
69 }
70 
71 bool bc_tmp112_get_temperature_raw(bc_tmp112_t *self, int16_t *raw)
72 {
73  if (!self->_temperature_valid)
74  {
75  return false;
76  }
77 
78  *raw = (int16_t) self->_reg_temperature >> 4;
79 
80  return true;
81 }
82 
84 {
85  int16_t raw;
86 
87  if (!bc_tmp112_get_temperature_raw(self, &raw))
88  {
89  return false;
90  }
91 
92  *celsius = (float) raw / 16.f;
93 
94  return true;
95 }
96 
97 bool bc_tmp112_get_temperature_fahrenheit(bc_tmp112_t *self, float *fahrenheit)
98 {
99  float celsius;
100 
101  if (!bc_tmp112_get_temperature_celsius(self, &celsius))
102  {
103  return false;
104  }
105 
106  *fahrenheit = celsius * 1.8f + 32.f;
107 
108  return true;
109 }
110 
112 {
113  float celsius;
114 
115  if (!bc_tmp112_get_temperature_celsius(self, &celsius))
116  {
117  return false;
118  }
119 
120  *kelvin = celsius + 273.15f;
121 
122  if (*kelvin < 0.f)
123  {
124  *kelvin = 0.f;
125  }
126 
127  return true;
128 }
129 
130 static void _bc_tmp112_task_interval(void *param)
131 {
132  bc_tmp112_t *self = param;
133 
134  bc_tmp112_measure(self);
135 
136  bc_scheduler_plan_current_relative(self->_update_interval);
137 }
138 
139 static void _bc_tmp112_task_measure(void *param)
140 {
141  bc_tmp112_t *self = param;
142 
143 start:
144 
145  switch (self->_state)
146  {
147  case BC_TMP112_STATE_ERROR:
148  {
149  self->_temperature_valid = false;
150 
151  self->_measurement_active = false;
152 
153  if (self->_event_handler != NULL)
154  {
155  self->_event_handler(self, BC_TMP112_EVENT_ERROR, self->_event_param);
156  }
157 
158  self->_state = BC_TMP112_STATE_INITIALIZE;
159 
160  return;
161  }
162  case BC_TMP112_STATE_INITIALIZE:
163  {
164  self->_state = BC_TMP112_STATE_ERROR;
165 
166  if (!bc_i2c_memory_write_16b(self->_i2c_channel, self->_i2c_address, 0x01, 0x0180))
167  {
168  goto start;
169  }
170 
171  self->_state = BC_TMP112_STATE_MEASURE;
172 
173  self->_tick_ready = bc_tick_get() + _BC_TMP112_DELAY_INITIALIZATION;
174 
175  if (self->_measurement_active)
176  {
177  bc_scheduler_plan_current_absolute(self->_tick_ready);
178  }
179 
180  return;
181  }
182  case BC_TMP112_STATE_MEASURE:
183  {
184  self->_state = BC_TMP112_STATE_ERROR;
185 
186  if (!bc_i2c_memory_write_8b(self->_i2c_channel, self->_i2c_address, 0x01, 0x81))
187  {
188  goto start;
189  }
190 
191  self->_state = BC_TMP112_STATE_READ;
192 
193  bc_scheduler_plan_current_from_now(_BC_TMP112_DELAY_MEASUREMENT);
194 
195  return;
196  }
197  case BC_TMP112_STATE_READ:
198  {
199  self->_state = BC_TMP112_STATE_ERROR;
200 
201  uint8_t reg_configuration;
202 
203  if (!bc_i2c_memory_read_8b(self->_i2c_channel, self->_i2c_address, 0x01, &reg_configuration))
204  {
205  goto start;
206  }
207 
208  if ((reg_configuration & 0x81) != 0x81)
209  {
210  goto start;
211  }
212 
213  if (!bc_i2c_memory_read_16b(self->_i2c_channel, self->_i2c_address, 0x00, &self->_reg_temperature))
214  {
215  goto start;
216  }
217 
218  self->_temperature_valid = true;
219 
220  self->_state = BC_TMP112_STATE_UPDATE;
221 
222  goto start;
223  }
224  case BC_TMP112_STATE_UPDATE:
225  {
226  self->_measurement_active = false;
227 
228  if (self->_event_handler != NULL)
229  {
230  self->_event_handler(self, BC_TMP112_EVENT_UPDATE, self->_event_param);
231  }
232 
233  self->_state = BC_TMP112_STATE_MEASURE;
234 
235  return;
236  }
237  default:
238  {
239  self->_state = BC_TMP112_STATE_ERROR;
240 
241  goto start;
242  }
243  }
244 }
void bc_tmp112_init(bc_tmp112_t *self, bc_i2c_channel_t i2c_channel, uint8_t i2c_address)
Initialize TMP112.
Definition: bc_tmp112.c:11
uint64_t bc_tick_t
Timestamp data type.
Definition: bc_tick.h:16
bool bc_i2c_memory_write_16b(bc_i2c_channel_t channel, uint8_t device_address, uint32_t memory_address, uint16_t data)
Memory write 2 bytes to I2C channel.
Definition: bc_i2c.c:414
I2C communication speed is 400 kHz.
Definition: bc_i2c.h:36
bc_tmp112_event_t
Callback events.
Definition: bc_tmp112.h:13
void bc_scheduler_plan_absolute(bc_scheduler_task_id_t task_id, bc_tick_t tick)
Schedule specified task to absolute tick.
Definition: bc_scheduler.c:124
bc_scheduler_task_id_t bc_scheduler_register(void(*task)(void *), void *param, bc_tick_t tick)
Register task in scheduler.
Definition: bc_scheduler.c:56
bool bc_i2c_memory_read_8b(bc_i2c_channel_t channel, uint8_t device_address, uint32_t memory_address, uint8_t *data)
Memory read 1 byte from I2C channel.
Definition: bc_i2c.c:431
void bc_scheduler_plan_current_absolute(bc_tick_t tick)
Schedule current task to absolute tick.
Definition: bc_scheduler.c:144
void bc_i2c_init(bc_i2c_channel_t channel, bc_i2c_speed_t speed)
Initialize I2C channel.
Definition: bc_i2c.c:54
Update event.
Definition: bc_tmp112.h:19
bc_tick_t bc_tick_get(void)
Get absolute timestamp since start of program.
Definition: bc_tick.c:7
bool bc_tmp112_get_temperature_fahrenheit(bc_tmp112_t *self, float *fahrenheit)
Get measured temperature in degrees of Fahrenheit.
Definition: bc_tmp112.c:97
void bc_tmp112_set_update_interval(bc_tmp112_t *self, bc_tick_t interval)
Set measurement interval.
Definition: bc_tmp112.c:41
void bc_scheduler_plan_current_relative(bc_tick_t tick)
Schedule current task to tick relative from current spin.
Definition: bc_scheduler.c:149
struct bc_tmp112_t bc_tmp112_t
TMP112 instance.
Definition: bc_tmp112.h:25
Error event.
Definition: bc_tmp112.h:16
bool bc_tmp112_get_temperature_kelvin(bc_tmp112_t *self, float *kelvin)
Get measured temperature in kelvin.
Definition: bc_tmp112.c:111
bool bc_tmp112_get_temperature_celsius(bc_tmp112_t *self, float *celsius)
Get measured temperature in degrees of Celsius.
Definition: bc_tmp112.c:83
void bc_scheduler_plan_relative(bc_scheduler_task_id_t task_id, bc_tick_t tick)
Schedule specified task to tick relative from current spin.
Definition: bc_scheduler.c:129
void bc_tmp112_set_event_handler(bc_tmp112_t *self, void(*event_handler)(bc_tmp112_t *, bc_tmp112_event_t, void *), void *event_param)
Set callback function.
Definition: bc_tmp112.c:35
bc_i2c_channel_t
I2C channels.
Definition: bc_i2c.h:15
void bc_scheduler_plan_current_from_now(bc_tick_t tick)
Schedule current task to tick relative from now.
Definition: bc_scheduler.c:154
#define BC_TICK_INFINITY
Maximum timestamp value.
Definition: bc_tick.h:12
bool bc_tmp112_measure(bc_tmp112_t *self)
Start measurement manually.
Definition: bc_tmp112.c:57
bool bc_i2c_memory_read_16b(bc_i2c_channel_t channel, uint8_t device_address, uint32_t memory_address, uint16_t *data)
Memory read 2 bytes from I2C channel.
Definition: bc_i2c.c:443
void bc_scheduler_unregister(bc_scheduler_task_id_t task_id)
Unregister specified task.
Definition: bc_scheduler.c:80
void bc_tmp112_deinit(bc_tmp112_t *self)
Deinitialize TMP112.
Definition: bc_tmp112.c:26
bool bc_tmp112_get_temperature_raw(bc_tmp112_t *self, int16_t *raw)
Get measured temperature as raw value.
Definition: bc_tmp112.c:71
bool bc_i2c_memory_write_8b(bc_i2c_channel_t channel, uint8_t device_address, uint32_t memory_address, uint8_t data)
Memory write 1 byte to I2C channel.
Definition: bc_i2c.c:402