1 /**
2 * \file
3 *
4 * \brief SAM Temperature Sensor (TSENS) Driver
5 *
6 * Copyright (C) 2015-2016 Atmel Corporation. All rights reserved.
7 *
8 * \asf_license_start
9 *
10 * \page License
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions are met:
14 *
15 * 1. Redistributions of source code must retain the above copyright notice,
16 * this list of conditions and the following disclaimer.
17 *
18 * 2. Redistributions in binary form must reproduce the above copyright notice,
19 * this list of conditions and the following disclaimer in the documentation
20 * and/or other materials provided with the distribution.
21 *
22 * 3. The name of Atmel may not be used to endorse or promote products derived
23 * from this software without specific prior written permission.
24 *
25 * 4. This software may only be redistributed and used in connection with an
26 * Atmel microcontroller product.
27 *
28 * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
29 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
30 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
31 * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
32 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
36 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
37 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38 * POSSIBILITY OF SUCH DAMAGE.
39 *
40 * \asf_license_stop
41 *
42 */
43 /*
44 * Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
45 */
46
47 #ifndef TSENS_H_INCLUDED
48 #define TSENS_H_INCLUDED
49
50 /**
51 * \defgroup asfdoc_sam0_tsens_group SAM Temperature Sensor (TSENS) Driver
52 *
53 * This driver for Atmel® | SMART ARM®-based microcontrollers provides
54 * an interface for the configuration and management of the device's
55 * Configurable Custom Logic functionality.
56 *
57 * The following peripheral is used by this module:
58 * - TSENS (Temperature Sensor)
59 *
60 * The following devices can use this module:
61 * - Atmel | SMART SAM C21
62 *
63 * The outline of this documentation is as follows:
64 * - \ref asfdoc_sam0_tsens_prerequisites
65 * - \ref asfdoc_sam0_tsens_module_overview
66 * - \ref asfdoc_sam0_tsens_special_considerations
67 * - \ref asfdoc_sam0_tsens_extra_info
68 * - \ref asfdoc_sam0_tsens_examples
69 * - \ref asfdoc_sam0_tsens_api_overview
70 *
71 *
72 * \section asfdoc_sam0_tsens_prerequisites Prerequisites
73 *
74 * There are no prerequisites for this module.
75 *
76 *
77 * \section asfdoc_sam0_tsens_module_overview Module Overview
78 *
79 * The Temperature Sensor (TSENS) can be used to accurately measure the operating
80 * temperature of the device. TSENS accurately measures the operating
81 * temperature of the device by comparing the difference in two temperature
82 * dependent frequencies to a known frequency. The frequency of the
83 * temperature dependent oscillator (TOSC) is measured twice: first with the
84 * min configuration and next with the maximum configuration. The resulting signed
85 * value is proportional to the temperature and is corrected for offset by the
86 * contents of the OFFSET register.
87 *
88 * Accurately measures a temperature:
89 * - ±1°C over 0°C ~ 60°C
90 * - ±3°C over -40°C ~ 85°C
91 * - ±5°C over -40°C ~ 105°C
92 *
93 * The number of periods of GCLK_TSENS used for the measurement is defined by
94 * the GAIN register. The width of the resulting pulse is measured using a
95 * counter clocked by GCLK_TSENS in the up direction for the 1<SUP>st</SUP> phase and in
96 * the down 2<SUP>nd</SUP> phase. Register GAIN and OFFSET is loaded from NVM, or can also
97 * be fixed by user.
98 * \f[
99 * VALUE = OFFSET + (\frac{f_{TOSCMIN} - f_{TOSCMAX}}{f_{GCLK}}) \times GAIN
100 * \f]
101 *
102 * \note If fix this bitfield, the relationship between GCLK frequency, GAIN
103 * and resolution as below:
104 * <table>
105 * <tr>
106 * <th>Resolution (#/°C)</th>
107 * <th>GAIN@48MHz</th>
108 * <th>GAIN@40MHz</th>
109 * </tr>
110 * <tr>
111 * <td>×1 (1°C)</td>
112 * <td>960</td>
113 * <td>800</td>
114 * </tr>
115 * <tr>
116 * <td>×10 (0.1°C)</td>
117 * <td>9600</td>
118 * <td>8000</td>
119 * </tr>
120 * <tr>
121 * <td>×100 (0.01°C)</td>
122 * <td>96000</td>
123 * <td>80000</td>
124 * </tr>
125 * </table>
126 *
127 * \subsection asfdoc_sam0_tsens_module_overview_window_monitor Window Monitor
128 * The TSENS module window monitor function can be used to automatically
129 * compare the conversion result against a predefined pair of upper and
130 * lower threshold values.
131 *
132 *
133 * \subsection asfdoc_sam0_tsens_module_overview_events Events
134 * Event generation and event actions are configurable in the TSENS.
135 *
136 * The TSENS has one actions that can be triggered upon event reception:
137 * \li Start conversion
138 *
139 * The TSENS can generate the following output event:
140 * \li Window monitor
141 *
142 * If the event actions are enabled in the configuration, any incoming event
143 * will trigger the action.
144 *
145 * If the window monitor event is enabled, an event will be generated
146 * when the configured window condition is detected.
147 *
148 * \section asfdoc_sam0_tsens_special_considerations Special Considerations
149 *
150 * There are no special considerations for this module.
151 *
152 *
153 * \section asfdoc_sam0_tsens_extra_info Extra Information
154 *
155 * For extra information, see \ref asfdoc_sam0_tsens_extra. This includes:
156 * - \ref asfdoc_sam0_tsens_extra_acronyms
157 * - \ref asfdoc_sam0_tsens_extra_dependencies
158 * - \ref asfdoc_sam0_tsens_extra_errata
159 * - \ref asfdoc_sam0_tsens_extra_history
160 *
161 *
162 * \section asfdoc_sam0_tsens_examples Examples
163 *
164 * For a list of examples related to this driver, see
165 * \ref asfdoc_sam0_tsens_exqsg.
166 *
167 *
168 * \section asfdoc_sam0_tsens_api_overview API Overview
169 * @{
170 */
171 #ifdef __cplusplus
172 extern "C" {
173 #endif
174
175 #include <compiler.h>
176 #include <system.h>
177
178 /**
179 * The magnitude of the temperature measurement value decreases with increasing
180 * temperature, i.e. it has a negative temperature coefficient.
181 * \ref asfdoc_sam0_tsens_extra_errata "Errata reference: 14476".
182 */
183 #define ERRATA_14476 true
184
185 /**
186 * \name Module Status Flags
187 *
188 * TSENS status flags, returned by \ref tsens_get_status() and cleared by
189 * \ref tsens_clear_status().
190 *
191 * @{
192 */
193
194 /** TSENS result ready. */
195 #define TSENS_STATUS_RESULT_READY (1UL << 0)
196 /** TSENS result overwritten before read. */
197 #define TSENS_STATUS_OVERRUN (1UL << 1)
198 /** Window monitor match. */
199 #define TSENS_STATUS_WINDOW (1UL << 2)
200 /** TSENS result overflows. */
201 #define TSENS_STATUS_OVERFLOW (1UL << 3)
202
203 /** @} */
204
205 /**
206 * \brief TSENS window monitor mode enum.
207 *
208 * Enum for the possible window monitor modes for the TSENS.
209 *
210 */
211 enum tsens_window_mode {
212 /** No window mode */
213 TSENS_WINDOW_MODE_DISABLE = TSENS_CTRLC_WINMODE_DISABLE,
214 /** RESULT > WINLT */
215 TSENS_WINDOW_MODE_ABOVE = TSENS_CTRLC_WINMODE_ABOVE,
216 /** RESULT < WINUT */
217 TSENS_WINDOW_MODE_BELOW = TSENS_CTRLC_WINMODE_BELOW,
218 /** WINLT < RESULT < WINUT */
219 TSENS_WINDOW_MODE_INSIDE = TSENS_CTRLC_WINMODE_INSIDE,
220 /** !(WINLT < RESULT < WINUT) */
221 TSENS_WINDOW_MODE_OUTSIDE = TSENS_CTRLC_WINMODE_OUTSIDE,
222 /** VALUE > WINUT with hysteresis to WINLT */
223 TSENS_WINDOW_MODE_HYST_ABOVE = TSENS_CTRLC_WINMODE_HYST_ABOVE,
224 /** VALUE < WINLT with hysteresis to WINUT */
225 TSENS_WINDOW_MODE_HYST_BELOW = TSENS_CTRLC_WINMODE_HYST_BELOW,
226 };
227
228 /**
229 * \brief TSENS event action enum.
230 *
231 * Enum for the possible actions to take on an incoming event.
232 *
233 */
234 enum tsens_event_action {
235 /** Event action disabled */
236 TSENS_EVENT_ACTION_DISABLED = 0,
237 /** Start conversion */
238 TSENS_EVENT_ACTION_START_CONV = TSENS_EVCTRL_STARTEI,
239 };
240
241 /**
242 * \brief Window monitor configuration structure.
243 *
244 * Window monitor configuration structure.
245 */
246 struct tsens_window_config {
247 /** Selected window mode */
248 enum tsens_window_mode window_mode;
249 /** Lower window value */
250 int32_t window_lower_value;
251 /** Upper window value */
252 int32_t window_upper_value;
253 };
254
255 /**
256 * \brief TSENS event enable/disable structure.
257 *
258 * Event flags for the TSENS module. This is used to enable and
259 * disable events via \ref tsens_enable_events() and \ref tsens_disable_events().
260 */
261 struct tsens_events {
262 /** Enable event generation on window monitor */
263 bool generate_event_on_window_monitor;
264 };
265
266 /**
267 * \brief Calibration configuration structure.
268 *
269 * Calibration configuration structure.
270 */
271 struct tsens_calibration {
272 /** Time amplifier gain */
273 uint32_t gain;
274 /** Offset correction */
275 int32_t offset;
276 };
277
278 /**
279 * \brief TSENS configuration structure.
280 *
281 * Configuration structure for an TSENS instance. This structure should be
282 * initialized by the \ref tsens_get_config_defaults() function before being
283 * modified by the user application.
284 */
285 struct tsens_config {
286 /** GCLK generator used to clock the peripheral */
287 enum gclk_generator clock_source;
288 /** Enables free running mode if true */
289 bool free_running;
290 /** Enables TSENS in standby sleep mode if true */
291 bool run_in_standby;
292 /** Window monitor configuration structure */
293 struct tsens_window_config window;
294 /** Event action to take on incoming event */
295 enum tsens_event_action event_action;
296 /** Calibration value */
297 struct tsens_calibration calibration;
298 };
299
300
301 /**
302 * \name Driver Initialization and Configuration
303 * @{
304 */
305 enum status_code tsens_init(struct tsens_config *config);
306 void tsens_get_config_defaults(struct tsens_config *const config);
307
308 /** @} */
309
310 /**
311 * \name Status Management
312 * @{
313 */
314
315 /**
316 * \brief Retrieves the current module status.
317 *
318 * Retrieves the status of the module, giving overall state information.
319 *
320 * \return Bit mask of TSENS status flags.
321 *
322 * \retval TSENS_STATUS_RESULT_READY TSENS result is ready to be read
323 * \retval TSENS_STATUS_OVERRUN TSENS result overwritten before read
324 * \retval TSENS_STATUS_WINDOW TSENS has detected a value inside the set
325 * window range
326 * \retval TSENS_STATUS_OVERFLOW TSENS result overflows
327 */
tsens_get_status(void)328 static inline uint32_t tsens_get_status(void)
329 {
330 uint32_t int_flags = TSENS->INTFLAG.reg;
331
332 uint32_t status_flags = 0;
333
334 /* Check for TSENS Result Ready */
335 if (int_flags & TSENS_INTFLAG_RESRDY) {
336 status_flags |= TSENS_STATUS_RESULT_READY;
337 }
338
339 /* Check for TSENS Overrun */
340 if (int_flags & TSENS_INTFLAG_OVERRUN) {
341 status_flags |= TSENS_STATUS_OVERRUN;
342 }
343
344 /* Check for TSENS Window Match */
345 if (int_flags & TSENS_INTFLAG_WINMON) {
346 status_flags |= TSENS_STATUS_WINDOW;
347 }
348
349 /* Check for TSENS overflow */
350 if (int_flags & TSENS_INTFLAG_OVF) {
351 status_flags |= TSENS_STATUS_OVERFLOW;
352 }
353
354 return status_flags;
355 }
356
357 /**
358 * \brief Clears a module status flag.
359 *
360 * Clears the given status flag of the module.
361 *
362 * \param[in] module_inst Pointer to the TSENS software instance struct
363 * \param[in] status_flags Bitmask of \c TSENS_STATUS_* flags to clear
364 */
tsens_clear_status(const uint32_t status_flags)365 static inline void tsens_clear_status(const uint32_t status_flags)
366 {
367 uint32_t int_flags = 0;
368
369 /* Check for TSENS Result Ready */
370 if (status_flags & TSENS_INTFLAG_RESRDY) {
371 int_flags |= TSENS_STATUS_RESULT_READY;
372 }
373
374 /* Check for TSENS Overrun */
375 if (status_flags & TSENS_INTFLAG_OVERRUN) {
376 int_flags |= TSENS_STATUS_OVERRUN;
377 }
378
379 /* Check for TSENS Window Match */
380 if (status_flags & TSENS_INTFLAG_WINMON) {
381 int_flags |= TSENS_STATUS_WINDOW;
382 }
383
384 /* Check for TSENS overflow */
385 if (status_flags & TSENS_INTFLAG_OVF) {
386 int_flags |= TSENS_STATUS_OVERFLOW;
387 }
388
389 /* Clear interrupt flag */
390 TSENS->INTFLAG.reg = int_flags;
391 }
392
393 /** @} */
394
395 /**
396 * \name Enable, Disable, and Reset TSENS Module, Start Conversion and Read Result
397 * @{
398 */
399
400 /**
401 * \brief Determines if the hardware module is currently synchronizing to the bus.
402 *
403 * Checks to see if the underlying hardware peripheral module(s) are currently
404 * synchronizing across multiple clock domains to the hardware bus. This
405 * function can be used to delay further operations on a module until such time
406 * that it is ready, to prevent blocking delays for synchronization in the
407 * user application.
408 *
409 * \return Synchronization status of the underlying hardware module(s).
410 *
411 * \retval true If the module synchronization is ongoing
412 * \retval false If the module has completed synchronization
413 */
tsens_is_syncing(void)414 static inline bool tsens_is_syncing(void)
415 {
416 if (TSENS->SYNCBUSY.reg) {
417 return true;
418 }
419
420 return false;
421 }
422
423 /**
424 * \brief Enables the TSENS module.
425 *
426 * Enables an TSENS module that has previously been configured.
427
428 */
tsens_enable(void)429 static inline void tsens_enable(void)
430 {
431 TSENS->CTRLA.reg |= TSENS_CTRLA_ENABLE;
432
433 while (tsens_is_syncing()) {
434 /* Wait for synchronization */
435 }
436 }
437
438 /**
439 * \brief Disables the TSENS module.
440 *
441 * Disables an TSENS module that was previously enabled.
442 *
443 */
tsens_disable(void)444 static inline void tsens_disable(void)
445 {
446 TSENS->INTENCLR.reg = TSENS_INTENCLR_MASK;
447 TSENS->INTFLAG.reg = TSENS_INTFLAG_MASK;
448 TSENS->CTRLA.reg &= ~TSENS_CTRLA_ENABLE;
449
450 while (tsens_is_syncing()) {
451 /* Wait for synchronization */
452 }
453 }
454
455 /**
456 * \brief Resets the TSENS module.
457 *
458 * Resets an TSENS module, clearing all module state and registers to their
459 * default values.
460 *
461 */
tsens_reset(void)462 static inline void tsens_reset(void)
463 {
464 /* Disable to make sure the pipeline is flushed before reset */
465 tsens_disable();
466
467 /* Software reset the module */
468 TSENS->CTRLA.reg |= TSENS_CTRLA_SWRST;
469
470 while (tsens_is_syncing()) {
471 /* Wait for synchronization */
472 }
473 }
474
475
476 /**
477 * \brief Enables an TSENS event output.
478 *
479 * Enables one or more input or output events to or from the TSENS module. See
480 * \ref tsens_events "tsens_events" for a list of events this module supports.
481 *
482 * \note Events cannot be altered while the module is enabled.
483 *
484 * \param[in] events Struct containing flags of events to enable
485 */
tsens_enable_events(struct tsens_events * const events)486 static inline void tsens_enable_events(struct tsens_events *const events)
487 {
488 /* Sanity check arguments */
489 Assert(events);
490
491 uint32_t event_mask = 0;
492
493 /* Configure Window Monitor event */
494 if (events->generate_event_on_window_monitor) {
495 event_mask |= TSENS_EVCTRL_WINEO;
496 }
497
498 TSENS->EVCTRL.reg |= event_mask;
499 }
500
501 /**
502 * \brief Disables an TSENS event output.
503 *
504 * Disables one or more output events to or from the TSENS module. See
505 * \ref tsens_events "tsens_events" for a list of events this module supports.
506 *
507 * \note Events cannot be altered while the module is enabled.
508 *
509 * \param[in] events Struct containing flags of events to disable
510 */
tsens_disable_events(struct tsens_events * const events)511 static inline void tsens_disable_events(struct tsens_events *const events)
512 {
513 /* Sanity check arguments */
514 Assert(events);
515
516 uint32_t event_mask = 0;
517
518 /* Configure Window Monitor event */
519 if (events->generate_event_on_window_monitor) {
520 event_mask |= TSENS_EVCTRL_WINEO;
521 }
522
523 TSENS->EVCTRL.reg &= ~event_mask;
524 }
525
526 /**
527 * \brief Start a TSENS conversion.
528 *
529 * Start a new TSENS conversion.
530 *
531 */
tsens_start_conversion(void)532 static inline void tsens_start_conversion(void)
533 {
534 TSENS->CTRLB.reg |= TSENS_CTRLB_START;
535
536 while (tsens_is_syncing()) {
537 /* Wait for synchronization */
538 }
539 }
540
541 enum status_code tsens_read(int32_t *result);
542 /** @} */
543 /** @} */
544
545
546 /**
547 * \page asfdoc_sam0_tsens_extra Extra Information for TSENS Driver
548 *
549 * \section asfdoc_sam0_tsens_extra_acronyms Acronym
550 * Below is a table listing the acronym used in this module, along with their
551 * intended meaning.
552 *
553 * <table>
554 * <tr>
555 * <th>Acronym</th>
556 * <th>Description</th>
557 * </tr>
558 * <tr>
559 * <td>TSENS</td>
560 * <td>Temperature Sensor</td>
561 * </tr>
562 * </table>
563 *
564 *
565 * \section asfdoc_sam0_tsens_extra_dependencies Dependencies
566 * This driver has no dependencies.
567 *
568 *
569 * \section asfdoc_sam0_tsens_extra_errata Errata
570 * Errata reference: 14476.
571 *
572 * The magnitude of the temperature measurement value decreases with increasing
573 * temperature, i.e. it has a negative temperature coefficient.
574 *
575 *
576 * \section asfdoc_sam0_tsens_extra_history Module History
577 * An overview of the module history is presented in the table below, with
578 * details on the enhancements and fixes made to the module since its first
579 * release. The current version of this corresponds to the newest version in
580 * the table.
581 *
582 * <table>
583 * <tr>
584 * <th>Changelog</th>
585 * </tr>
586 * <tr>
587 * <td>Initial Release</td>
588 * </tr>
589 * </table>
590 */
591
592 /**
593 * \page asfdoc_sam0_tsens_exqsg Examples for TSENS Driver
594 *
595 * This is a list of the available Quick Start guides (QSGs) and example
596 * applications for \ref asfdoc_sam0_tsens_group. QSGs are simple examples with
597 * step-by-step instructions to configure and use this driver in a selection of
598 * use cases. Note that a QSG can be compiled as a standalone application or be
599 * added to the user application.
600 *
601 * - \subpage asfdoc_sam0_tsens_basic_use_case
602 * - \subpage asfdoc_sam0_tsens_basic_use_case_callback
603 *
604 * \page asfdoc_sam0_tsens_document_revision_history Document Revision History
605 *
606 * <table>
607 * <tr>
608 * <th>Doc. Rev.</th>
609 * <th>Date</th>
610 * <th>Comments</th>
611 * </tr>
612 * <tr>
613 * <td>42542A</td>
614 * <td>12/2015</td>
615 * <td>Initial document release</td>
616 * </tr>
617 * </table>
618 */
619
620 #ifdef __cplusplus
621 }
622 #endif
623
624 #endif /* TSENS_H_INCLUDED */
625
626