Firmware SDK
twr_tmp112.c
1 #include <twr_tmp112.h>
2 
3 #define _TWR_TMP112_DELAY_RUN 50
4 #define _TWR_TMP112_DELAY_INITIALIZATION 50
5 #define _TWR_TMP112_DELAY_MEASUREMENT 50
6 
7 static void _twr_tmp112_task_interval(void *param);
8 
9 static void _twr_tmp112_task_measure(void *param);
10 
11 void twr_tmp112_init(twr_tmp112_t *self, twr_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 = twr_scheduler_register(_twr_tmp112_task_interval, self, TWR_TICK_INFINITY);
19  self->_task_id_measure = twr_scheduler_register(_twr_tmp112_task_measure, self, _TWR_TMP112_DELAY_RUN);
20 
21  self->_tick_ready = _TWR_TMP112_DELAY_RUN;
22 
23  twr_i2c_init(self->_i2c_channel, TWR_I2C_SPEED_400_KHZ);
24 }
25 
27 {
28  twr_i2c_memory_write_16b(self->_i2c_channel, self->_i2c_address, 0x01, 0x0180);
29 
30  twr_scheduler_unregister(self->_task_id_interval);
31 
32  twr_scheduler_unregister(self->_task_id_measure);
33 }
34 
35 void twr_tmp112_set_event_handler(twr_tmp112_t *self, void (*event_handler)(twr_tmp112_t *, twr_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 == TWR_TICK_INFINITY)
46  {
47  twr_scheduler_plan_absolute(self->_task_id_interval, TWR_TICK_INFINITY);
48  }
49  else
50  {
51  twr_scheduler_plan_relative(self->_task_id_interval, self->_update_interval);
52 
53  twr_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  twr_scheduler_plan_absolute(self->_task_id_measure, self->_tick_ready);
67 
68  return true;
69 }
70 
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 (!twr_tmp112_get_temperature_raw(self, &raw))
88  {
89  return false;
90  }
91 
92  *celsius = (float) raw / 16.f;
93 
94  return true;
95 }
96 
98 {
99  float celsius;
100 
101  if (!twr_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 (!twr_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 _twr_tmp112_task_interval(void *param)
131 {
132  twr_tmp112_t *self = param;
133 
134  twr_tmp112_measure(self);
135 
136  twr_scheduler_plan_current_relative(self->_update_interval);
137 }
138 
139 static void _twr_tmp112_task_measure(void *param)
140 {
141  twr_tmp112_t *self = param;
142 
143 start:
144 
145  switch (self->_state)
146  {
147  case TWR_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, TWR_TMP112_EVENT_ERROR, self->_event_param);
156  }
157 
158  self->_state = TWR_TMP112_STATE_INITIALIZE;
159 
160  return;
161  }
162  case TWR_TMP112_STATE_INITIALIZE:
163  {
164  self->_state = TWR_TMP112_STATE_ERROR;
165 
166  if (!twr_i2c_memory_write_16b(self->_i2c_channel, self->_i2c_address, 0x01, 0x0180))
167  {
168  goto start;
169  }
170 
171  self->_state = TWR_TMP112_STATE_MEASURE;
172 
173  self->_tick_ready = twr_tick_get() + _TWR_TMP112_DELAY_INITIALIZATION;
174 
175  if (self->_measurement_active)
176  {
177  twr_scheduler_plan_current_absolute(self->_tick_ready);
178  }
179 
180  return;
181  }
182  case TWR_TMP112_STATE_MEASURE:
183  {
184  self->_state = TWR_TMP112_STATE_ERROR;
185 
186  if (!twr_i2c_memory_write_8b(self->_i2c_channel, self->_i2c_address, 0x01, 0x81))
187  {
188  goto start;
189  }
190 
191  self->_state = TWR_TMP112_STATE_READ;
192 
193  twr_scheduler_plan_current_from_now(_TWR_TMP112_DELAY_MEASUREMENT);
194 
195  return;
196  }
197  case TWR_TMP112_STATE_READ:
198  {
199  self->_state = TWR_TMP112_STATE_ERROR;
200 
201  uint8_t reg_configuration;
202 
203  if (!twr_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 (!twr_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 = TWR_TMP112_STATE_UPDATE;
221 
222  goto start;
223  }
224  case TWR_TMP112_STATE_UPDATE:
225  {
226  self->_measurement_active = false;
227 
228  if (self->_event_handler != NULL)
229  {
230  self->_event_handler(self, TWR_TMP112_EVENT_UPDATE, self->_event_param);
231  }
232 
233  self->_state = TWR_TMP112_STATE_MEASURE;
234 
235  return;
236  }
237  default:
238  {
239  self->_state = TWR_TMP112_STATE_ERROR;
240 
241  goto start;
242  }
243  }
244 }
void twr_scheduler_plan_relative(twr_scheduler_task_id_t task_id, twr_tick_t tick)
Schedule specified task to tick relative from current spin.
bool twr_i2c_memory_write_16b(twr_i2c_channel_t channel, uint8_t device_address, uint32_t memory_address, uint16_t data)
Memory write 2 bytes to I2C channel.
Definition: twr_i2c.c:420
void twr_scheduler_plan_current_relative(twr_tick_t tick)
Schedule current task to tick relative from current spin.
bool twr_tmp112_measure(twr_tmp112_t *self)
Start measurement manually.
Definition: twr_tmp112.c:57
Update event.
Definition: twr_tmp112.h:19
twr_scheduler_task_id_t twr_scheduler_register(void(*task)(void *), void *param, twr_tick_t tick)
Register task in scheduler.
Definition: twr_scheduler.c:53
void twr_scheduler_plan_current_absolute(twr_tick_t tick)
Schedule current task to absolute tick.
void twr_tmp112_set_update_interval(twr_tmp112_t *self, twr_tick_t interval)
Set measurement interval.
Definition: twr_tmp112.c:41
void twr_scheduler_plan_current_from_now(twr_tick_t tick)
Schedule current task to tick relative from now.
Error event.
Definition: twr_tmp112.h:16
void twr_i2c_init(twr_i2c_channel_t channel, twr_i2c_speed_t speed)
Initialize I2C channel.
Definition: twr_i2c.c:57
twr_tmp112_event_t
Callback events.
Definition: twr_tmp112.h:13
bool twr_i2c_memory_read_16b(twr_i2c_channel_t channel, uint8_t device_address, uint32_t memory_address, uint16_t *data)
Memory read 2 bytes from I2C channel.
Definition: twr_i2c.c:449
uint64_t twr_tick_t
Timestamp data type.
Definition: twr_tick.h:16
bool twr_i2c_memory_write_8b(twr_i2c_channel_t channel, uint8_t device_address, uint32_t memory_address, uint8_t data)
Memory write 1 byte to I2C channel.
Definition: twr_i2c.c:408
twr_tick_t twr_tick_get(void)
Get absolute timestamp since start of program.
Definition: twr_tick.c:7
bool twr_tmp112_get_temperature_raw(twr_tmp112_t *self, int16_t *raw)
Get measured temperature as raw value.
Definition: twr_tmp112.c:71
twr_i2c_channel_t
I2C channels.
Definition: twr_i2c.h:15
void twr_scheduler_unregister(twr_scheduler_task_id_t task_id)
Unregister specified task.
Definition: twr_scheduler.c:77
void twr_tmp112_set_event_handler(twr_tmp112_t *self, void(*event_handler)(twr_tmp112_t *, twr_tmp112_event_t, void *), void *event_param)
Set callback function.
Definition: twr_tmp112.c:35
bool twr_tmp112_get_temperature_kelvin(twr_tmp112_t *self, float *kelvin)
Get measured temperature in kelvin.
Definition: twr_tmp112.c:111
bool twr_i2c_memory_read_8b(twr_i2c_channel_t channel, uint8_t device_address, uint32_t memory_address, uint8_t *data)
Memory read 1 byte from I2C channel.
Definition: twr_i2c.c:437
bool twr_tmp112_get_temperature_fahrenheit(twr_tmp112_t *self, float *fahrenheit)
Get measured temperature in degrees of Fahrenheit.
Definition: twr_tmp112.c:97
#define TWR_TICK_INFINITY
Maximum timestamp value.
Definition: twr_tick.h:12
void twr_scheduler_plan_absolute(twr_scheduler_task_id_t task_id, twr_tick_t tick)
Schedule specified task to absolute tick.
void twr_tmp112_init(twr_tmp112_t *self, twr_i2c_channel_t i2c_channel, uint8_t i2c_address)
Initialize TMP112.
Definition: twr_tmp112.c:11
bool twr_tmp112_get_temperature_celsius(twr_tmp112_t *self, float *celsius)
Get measured temperature in degrees of Celsius.
Definition: twr_tmp112.c:83
void twr_tmp112_deinit(twr_tmp112_t *self)
Deinitialize TMP112.
Definition: twr_tmp112.c:26
I2C communication speed is 400 kHz.
Definition: twr_i2c.h:36
struct twr_tmp112_t twr_tmp112_t
TMP112 instance.
Definition: twr_tmp112.h:25