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&reg; | SMART ARM&reg;-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>&times;1 (1°C)</td>
112  *    <td>960</td>
113  *    <td>800</td>
114  *  </tr>
115  *	<tr>
116  *	  <td>&times;10 (0.1°C)</td>
117  *    <td>9600</td>
118  *    <td>8000</td>
119  *  </tr>
120  *	<tr>
121  *	  <td>&times;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