1 /*
2 * Copyright (c) 2023 Nordic Semiconductor ASA
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 /*
8 * TEMP - Temperature sensor
9 * https://infocenter.nordicsemi.com/topic/ps_nrf52833/temp.html?cp=4_1_0_5_25
10 *
11 * A very simple and rough model
12 *
13 * Notes:
14 * * At this point the device is always at 25 C
15 * * The measurement result will just be 25 +- 0.25 C
16 * * There is no per device variability
17 * * There is no modeling of possible calibration errors or inaccuracies due to no non-linearities compensation
18 */
19
20 #include <string.h>
21 #include <stdbool.h>
22 #include <stdint.h>
23 #include "bs_rand_main.h"
24 #include "nsi_tasks.h"
25 #include "nsi_hws_models_if.h"
26 #include "nsi_hw_scheduler.h"
27 #include "NHW_common_types.h"
28 #include "NHW_config.h"
29 #include "NHW_templates.h"
30 #include "NHW_TEMP.h"
31 #include "NHW_peri_types.h"
32 #include "NHW_xPPI.h"
33 #include "irq_ctrl.h"
34
35 #if NHW_TEMP_TOTAL_INST > 1
36 #error "This model only supports 1 instance so far"
37 #endif
38
39 NRF_TEMP_Type NRF_TEMP_regs;
40
41 #if (NHW_HAS_DPPI)
42 /* Mapping of peripheral instance to DPPI instance */
43 static uint nhw_TEMP_dppi_map[NHW_TEMP_TOTAL_INST] = NHW_TEMP_DPPI_MAP;
44 #endif
45
46 static bs_time_t Timer_TEMP = TIME_NEVER; //Time when the next temperature measurement will be ready
47
48 static bool TEMP_hw_started;
49 static uint32_t TEMP_INTEN; //interrupt enable
50
51 static double temperature = 25.0; /* Actual temperature the device is at */
52
53 /**
54 * Initialize the TEMP model
55 */
nhw_temp_init(void)56 static void nhw_temp_init(void) {
57 memset(&NRF_TEMP_regs, 0, sizeof(NRF_TEMP_regs));
58 #if defined(NRF52833)
59 NRF_TEMP_regs.A0 = 0x00000326;
60 NRF_TEMP_regs.A1 = 0x00000348;
61 NRF_TEMP_regs.A2 = 0x000003AA;
62 NRF_TEMP_regs.A3 = 0x0000040E;
63 NRF_TEMP_regs.A4 = 0x000004BD;
64 NRF_TEMP_regs.A5 = 0x000005A3;
65 NRF_TEMP_regs.B0 = 0x00003FEF;
66 NRF_TEMP_regs.B1 = 0x00003FBE;
67 NRF_TEMP_regs.B2 = 0x00003FBE;
68 NRF_TEMP_regs.B3 = 0x00000012;
69 NRF_TEMP_regs.B4 = 0x00000124;
70 NRF_TEMP_regs.B5 = 0x0000027C;
71 NRF_TEMP_regs.T0 = 0x000000E2;
72 NRF_TEMP_regs.T1 = 0x00000000;
73 NRF_TEMP_regs.T2 = 0x00000019;
74 NRF_TEMP_regs.T3 = 0x0000003C;
75 NRF_TEMP_regs.T4 = 0x00000050;
76 #elif defined(NRF5340)
77 NRF_TEMP_regs.A0 = 0x000002D9;
78 NRF_TEMP_regs.A1 = 0x00000322;
79 NRF_TEMP_regs.A2 = 0x00000355;
80 NRF_TEMP_regs.A3 = 0x000003DF;
81 NRF_TEMP_regs.A4 = 0x0000044E;
82 NRF_TEMP_regs.A5 = 0x000004B7;
83 NRF_TEMP_regs.B0 = 0x00000FC7;
84 NRF_TEMP_regs.B1 = 0x00000F71;
85 NRF_TEMP_regs.B2 = 0x00000F6C;
86 NRF_TEMP_regs.B3 = 0x00000FCB;
87 NRF_TEMP_regs.B4 = 0x0000004B;
88 NRF_TEMP_regs.B5 = 0x000000F6;
89 NRF_TEMP_regs.T0 = 0x000000E1;
90 NRF_TEMP_regs.T1 = 0x000000F9;
91 NRF_TEMP_regs.T2 = 0x00000010;
92 NRF_TEMP_regs.T3 = 0x00000026;
93 NRF_TEMP_regs.T4 = 0x0000003F;
94 #endif
95
96 TEMP_hw_started = false;
97 TEMP_INTEN = 0;
98 Timer_TEMP = TIME_NEVER;
99 }
100
101 NSI_TASK(nhw_temp_init, HW_INIT, 100);
102
103 /**
104 * TASK_START triggered handler
105 */
nhw_TEMP_TASK_START(void)106 void nhw_TEMP_TASK_START(void) {
107 if (TEMP_hw_started) {
108 return;
109 }
110 TEMP_hw_started = true;
111 Timer_TEMP = nsi_hws_get_time() + NHW_TEMP_t_TEMP;
112 nsi_hws_find_next_event();
113 }
114
115 /**
116 * TASK_STOP triggered handler
117 */
nhw_TEMP_TASK_STOP(void)118 void nhw_TEMP_TASK_STOP(void) {
119 TEMP_hw_started = false;
120 Timer_TEMP = TIME_NEVER;
121 nsi_hws_find_next_event();
122 }
123
nhw_TEMP_eval_interrupt(uint inst)124 static void nhw_TEMP_eval_interrupt(uint inst) {
125 static bool temp_int_line[NHW_TEMP_TOTAL_INST]; /* Is the TEMP currently driving its interrupt line high */
126 /* Mapping of peripheral instance to {int controller instance, int number} */
127 static struct nhw_irq_mapping nhw_temp_irq_map[NHW_TEMP_TOTAL_INST] = NHW_TEMP_INT_MAP;
128 bool new_int_line = false;
129
130 NHW_CHECK_INTERRUPT_si(TEMP, DATARDY, TEMP_INTEN)
131
132 hw_irq_ctrl_toggle_level_irq_line_if(&temp_int_line[inst],
133 new_int_line,
134 &nhw_temp_irq_map[inst]);
135 }
136
137 NHW_SIDEEFFECTS_INTSET_si(TEMP, NRF_TEMP_regs., TEMP_INTEN)
138 NHW_SIDEEFFECTS_INTCLR_si(TEMP, NRF_TEMP_regs., TEMP_INTEN)
139
NHW_SIDEEFFECTS_EVENTS(TEMP)140 NHW_SIDEEFFECTS_EVENTS(TEMP)
141
142 NHW_SIDEEFFECTS_TASKS_si(TEMP, START)
143 NHW_SIDEEFFECTS_TASKS_si(TEMP, STOP)
144
145 #if (NHW_HAS_DPPI)
146 NHW_SIDEEFFECTS_SUBSCRIBE_si(TEMP, START)
147 NHW_SIDEEFFECTS_SUBSCRIBE_si(TEMP, STOP)
148 #endif /* NHW_HAS_DPPI */
149
150 static NHW_SIGNAL_EVENT_si(TEMP, DATARDY)
151
152 /**
153 * Time has come when the temperature measurement is ready
154 */
155 static void nhw_temp_timer_triggered(void) {
156
157 NRF_TEMP_regs.TEMP = temperature*(1 << NHW_TEMP_FBITS) + bs_random_uniformRi(-1,1);
158
159 TEMP_hw_started = false;
160 Timer_TEMP = TIME_NEVER;
161 nsi_hws_find_next_event();
162
163 nhw_TEMP_signal_EVENTS_DATARDY(0);
164 }
165
166 NSI_HW_EVENT(Timer_TEMP, nhw_temp_timer_triggered, 50);
167