1 /*
2  * Copyright (c) 2015 - 2020, Nordic Semiconductor ASA
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright notice, this
9  *    list of conditions and the following disclaimer.
10  *
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * 3. Neither the name of the copyright holder nor the names of its
16  *    contributors may be used to endorse or promote products derived from this
17  *    software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29  * POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 #include <nrfx.h>
33 
34 #if NRFX_CHECK(NRFX_QDEC_ENABLED)
35 
36 #include <nrfx_qdec.h>
37 #include <hal/nrf_gpio.h>
38 
39 #define NRFX_LOG_MODULE QDEC
40 #include <nrfx_log.h>
41 
42 #define EVT_TO_STR(event)                                             \
43     (event == NRF_QDEC_EVENT_SAMPLERDY ? "NRF_QDEC_EVENT_SAMPLERDY" : \
44     (event == NRF_QDEC_EVENT_REPORTRDY ? "NRF_QDEC_EVENT_REPORTRDY" : \
45     (event == NRF_QDEC_EVENT_ACCOF     ? "NRF_QDEC_EVENT_ACCOF"     : \
46                                          "UNKNOWN EVENT")))
47 
48 
49 static nrfx_qdec_event_handler_t m_qdec_event_handler = NULL;
50 static nrfx_drv_state_t m_state = NRFX_DRV_STATE_UNINITIALIZED;
51 
nrfx_qdec_irq_handler(void)52 void nrfx_qdec_irq_handler(void)
53 {
54     nrfx_qdec_event_t event;
55     if ( nrf_qdec_event_check(NRF_QDEC, NRF_QDEC_EVENT_SAMPLERDY) &&
56          nrf_qdec_int_enable_check(NRF_QDEC, NRF_QDEC_INT_SAMPLERDY_MASK) )
57     {
58         nrf_qdec_event_clear(NRF_QDEC, NRF_QDEC_EVENT_SAMPLERDY);
59         NRFX_LOG_DEBUG("Event: %s.", EVT_TO_STR(NRF_QDEC_EVENT_SAMPLERDY));
60 
61         event.type = NRF_QDEC_EVENT_SAMPLERDY;
62         event.data.sample.value = (int8_t)nrf_qdec_sample_get(NRF_QDEC);
63         m_qdec_event_handler(event);
64     }
65 
66     if ( nrf_qdec_event_check(NRF_QDEC, NRF_QDEC_EVENT_REPORTRDY) &&
67          nrf_qdec_int_enable_check(NRF_QDEC, NRF_QDEC_INT_REPORTRDY_MASK) )
68     {
69         nrf_qdec_event_clear(NRF_QDEC, NRF_QDEC_EVENT_REPORTRDY);
70         NRFX_LOG_DEBUG("Event: %s.", EVT_TO_STR(NRF_QDEC_EVENT_REPORTRDY));
71 
72         event.type = NRF_QDEC_EVENT_REPORTRDY;
73 
74         event.data.report.acc    = (int16_t)nrf_qdec_accread_get(NRF_QDEC);
75         event.data.report.accdbl = (uint16_t)nrf_qdec_accdblread_get(NRF_QDEC);
76         m_qdec_event_handler(event);
77     }
78 
79     if ( nrf_qdec_event_check(NRF_QDEC, NRF_QDEC_EVENT_ACCOF) &&
80          nrf_qdec_int_enable_check(NRF_QDEC, NRF_QDEC_INT_ACCOF_MASK) )
81     {
82         nrf_qdec_event_clear(NRF_QDEC, NRF_QDEC_EVENT_ACCOF);
83         NRFX_LOG_DEBUG("Event: %s.", EVT_TO_STR(NRF_QDEC_EVENT_ACCOF));
84 
85         event.type = NRF_QDEC_EVENT_ACCOF;
86         m_qdec_event_handler(event);
87     }
88 }
89 
90 
nrfx_qdec_init(nrfx_qdec_config_t const * p_config,nrfx_qdec_event_handler_t event_handler)91 nrfx_err_t nrfx_qdec_init(nrfx_qdec_config_t const * p_config,
92                           nrfx_qdec_event_handler_t  event_handler)
93 {
94     NRFX_ASSERT(p_config);
95     NRFX_ASSERT(event_handler);
96     nrfx_err_t err_code;
97 
98     if (m_state != NRFX_DRV_STATE_UNINITIALIZED)
99     {
100         err_code = NRFX_ERROR_INVALID_STATE;
101         NRFX_LOG_WARNING("Function: %s, error code: %s.",
102                          __func__,
103                          NRFX_LOG_ERROR_STRING_GET(err_code));
104         return err_code;
105     }
106 
107     m_qdec_event_handler = event_handler;
108 
109     nrf_qdec_sampleper_set(NRF_QDEC, p_config->sampleper);
110     nrf_gpio_cfg_input(p_config->psela, NRF_GPIO_PIN_NOPULL);
111     nrf_gpio_cfg_input(p_config->pselb, NRF_GPIO_PIN_NOPULL);
112     if (p_config->pselled != NRF_QDEC_LED_NOT_CONNECTED)
113     {
114         nrf_gpio_cfg_input(p_config->pselled, NRF_GPIO_PIN_NOPULL);
115         nrf_qdec_ledpre_set(NRF_QDEC, p_config->ledpre);
116         nrf_qdec_ledpol_set(NRF_QDEC, p_config->ledpol);
117     }
118     nrf_qdec_pins_set(NRF_QDEC, p_config->psela, p_config->pselb, p_config->pselled);
119     nrf_qdec_shorts_enable(NRF_QDEC, NRF_QDEC_SHORT_REPORTRDY_READCLRACC_MASK);
120 
121     if (p_config->dbfen)
122     {
123         nrf_qdec_dbfen_enable(NRF_QDEC);
124     }
125     else
126     {
127         nrf_qdec_dbfen_disable(NRF_QDEC);
128     }
129 
130     uint32_t int_mask = NRF_QDEC_INT_ACCOF_MASK;
131 
132     if (p_config->reportper != NRF_QDEC_REPORTPER_DISABLED)
133     {
134         nrf_qdec_reportper_set(NRF_QDEC, p_config->reportper);
135         int_mask |= NRF_QDEC_INT_REPORTRDY_MASK;
136     }
137 
138     if (p_config->sample_inten)
139     {
140         int_mask |= NRF_QDEC_INT_SAMPLERDY_MASK;
141     }
142 
143     nrf_qdec_int_enable(NRF_QDEC, int_mask);
144     NRFX_IRQ_PRIORITY_SET(nrfx_get_irq_number(NRF_QDEC), p_config->interrupt_priority);
145     NRFX_IRQ_ENABLE(nrfx_get_irq_number(NRF_QDEC));
146 
147     m_state = NRFX_DRV_STATE_INITIALIZED;
148 
149     err_code = NRFX_SUCCESS;
150     NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
151     return err_code;
152 }
153 
nrfx_qdec_uninit(void)154 void nrfx_qdec_uninit(void)
155 {
156     NRFX_ASSERT(m_state != NRFX_DRV_STATE_UNINITIALIZED);
157     nrfx_qdec_disable();
158     NRFX_IRQ_DISABLE(nrfx_get_irq_number(NRF_QDEC));
159 
160     nrf_gpio_cfg_default(nrf_qdec_phase_a_pin_get(NRF_QDEC));
161     nrf_gpio_cfg_default(nrf_qdec_phase_b_pin_get(NRF_QDEC));
162 
163     uint32_t led_pin = nrf_qdec_led_pin_get(NRF_QDEC);
164     if (led_pin != NRF_QDEC_LED_NOT_CONNECTED)
165     {
166         nrf_gpio_cfg_default(led_pin);
167     }
168 
169     m_state = NRFX_DRV_STATE_UNINITIALIZED;
170     NRFX_LOG_INFO("Uninitialized.");
171 }
172 
nrfx_qdec_enable(void)173 void nrfx_qdec_enable(void)
174 {
175     NRFX_ASSERT(m_state == NRFX_DRV_STATE_INITIALIZED);
176     nrf_qdec_enable(NRF_QDEC);
177     nrf_qdec_task_trigger(NRF_QDEC, NRF_QDEC_TASK_START);
178     m_state = NRFX_DRV_STATE_POWERED_ON;
179     NRFX_LOG_INFO("Enabled.");
180 }
181 
nrfx_qdec_disable(void)182 void nrfx_qdec_disable(void)
183 {
184     NRFX_ASSERT(m_state == NRFX_DRV_STATE_POWERED_ON);
185     nrf_qdec_task_trigger(NRF_QDEC, NRF_QDEC_TASK_STOP);
186     nrf_qdec_disable(NRF_QDEC);
187     m_state = NRFX_DRV_STATE_INITIALIZED;
188     NRFX_LOG_INFO("Disabled.");
189 }
190 
nrfx_qdec_accumulators_read(int16_t * p_acc,int16_t * p_accdbl)191 void nrfx_qdec_accumulators_read(int16_t * p_acc, int16_t * p_accdbl)
192 {
193     NRFX_ASSERT(m_state == NRFX_DRV_STATE_POWERED_ON);
194     nrf_qdec_task_trigger(NRF_QDEC, NRF_QDEC_TASK_READCLRACC);
195 
196     *p_acc    = (int16_t)nrf_qdec_accread_get(NRF_QDEC);
197     *p_accdbl = (int16_t)nrf_qdec_accdblread_get(NRF_QDEC);
198 
199     NRFX_LOG_DEBUG("Accumulators data, ACC register:");
200     NRFX_LOG_HEXDUMP_DEBUG((uint8_t *)p_acc, sizeof(p_acc[0]));
201     NRFX_LOG_DEBUG("Accumulators data, ACCDBL register:");
202     NRFX_LOG_HEXDUMP_DEBUG((uint8_t *)p_accdbl, sizeof(p_accdbl[0]));
203 }
204 
205 #endif // NRFX_CHECK(NRFX_QDEC_ENABLED)
206