Contiki-NG
ac-dimmer.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2016, Zolertia - http://www.zolertia.com
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
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  * notice, this list of conditions and the following disclaimer in the
12  * documentation and/or other materials provided with the distribution.
13  * 3. Neither the name of the Institute nor the names of its contributors
14  * may be used to endorse or promote products derived from this software
15  * without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  *
29  */
30 /*---------------------------------------------------------------------------*/
31 /**
32  * \addtogroup zoul-ac-dimmer
33  * @{
34  *
35  * \file
36  * Driver for the Krida Electronics AC light dimmer with zero-crossing, using
37  * a 50Hz frequency as reference (1/50Hz) ~20ms and 10ms half-cycle
38  */
39 /*---------------------------------------------------------------------------*/
40 #include "contiki.h"
41 #include "ac-dimmer.h"
42 #include "dev/gpio.h"
43 #include "dev/gpio-hal.h"
44 #include "lib/sensors.h"
45 #include "dev/ioc.h"
46 /*---------------------------------------------------------------------------*/
47 #define DIMMER_SYNC_PORT_BASE GPIO_PORT_TO_BASE(DIMMER_SYNC_PORT)
48 #define DIMMER_SYNC_PIN_MASK GPIO_PIN_MASK(DIMMER_SYNC_PIN)
49 #define DIMMER_GATE_PORT_BASE GPIO_PORT_TO_BASE(DIMMER_GATE_PORT)
50 #define DIMMER_GATE_PIN_MASK GPIO_PIN_MASK(DIMMER_GATE_PIN)
51 /*---------------------------------------------------------------------------*/
52 static uint8_t enabled;
53 static uint8_t dimming;
54 /*---------------------------------------------------------------------------*/
55 PROCESS(ac_dimmer_int_process, "AC Dimmer zero-cross interrupt process");
56 /*---------------------------------------------------------------------------*/
57 PROCESS_THREAD(ac_dimmer_int_process, ev, data)
58 {
60  PROCESS_BEGIN();
61 
62  int dimtime;
63 
64  while(1) {
65  PROCESS_YIELD_UNTIL(ev == PROCESS_EVENT_POLL);
66  dimtime = (uint8_t)(100 - dimming);
67  dimtime *= 100;
68 
69  /* Off cycle */
70  clock_delay_usec(dimtime);
71  GPIO_SET_PIN(DIMMER_GATE_PORT_BASE, DIMMER_GATE_PIN_MASK);
72  /* Triac on propagation delay */
73  clock_delay_usec(DIMMER_DEFAULT_GATE_PULSE_US);
74  GPIO_CLR_PIN(DIMMER_GATE_PORT_BASE, DIMMER_GATE_PIN_MASK);
75  }
76  PROCESS_END();
77 }
78 /*---------------------------------------------------------------------------*/
79 static void
80 dimmer_zero_cross_int_handler(gpio_hal_pin_mask_t pin_mask)
81 {
82  process_poll(&ac_dimmer_int_process);
83 }
84 /*---------------------------------------------------------------------------*/
85 static gpio_hal_event_handler_t dimmer_handler = {
86  .next = NULL,
87  .handler = dimmer_zero_cross_int_handler,
88  .pin_mask = gpio_hal_pin_to_mask(DIMMER_SYNC_PIN) << (DIMMER_SYNC_PORT << 3),
89 };
90 /*---------------------------------------------------------------------------*/
91 static int
92 status(int type)
93 {
94  switch(type) {
95  case SENSORS_ACTIVE:
96  return dimming;
97  case SENSORS_READY:
98  return enabled;
99  }
100  return DIMMER_ERROR;
101 }
102 /*---------------------------------------------------------------------------*/
103 static int
104 value(int type)
105 {
106  if(!enabled) {
107  return DIMMER_ERROR;
108  }
109 
110  dimming = (uint8_t)type;
111  return DIMMER_SUCCESS;
112 }
113 /*---------------------------------------------------------------------------*/
114 static int
115 configure(int type, int value)
116 {
117  if(type != SENSORS_ACTIVE) {
118  return DIMMER_ERROR;
119  }
120 
121  if(value) {
122  /* This is the Triac's gate pin */
123  GPIO_SOFTWARE_CONTROL(DIMMER_GATE_PORT_BASE, DIMMER_GATE_PIN_MASK);
124  GPIO_SET_OUTPUT(DIMMER_GATE_PORT_BASE, DIMMER_GATE_PIN_MASK);
125  ioc_set_over(DIMMER_GATE_PORT, DIMMER_GATE_PIN, IOC_OVERRIDE_OE);
126  GPIO_CLR_PIN(DIMMER_GATE_PORT_BASE, DIMMER_GATE_PIN_MASK);
127 
128  /* This is the zero-crossing pin and interrupt */
129  GPIO_SOFTWARE_CONTROL(DIMMER_SYNC_PORT_BASE, DIMMER_SYNC_PIN_MASK);
130  GPIO_SET_INPUT(DIMMER_SYNC_PORT_BASE, DIMMER_SYNC_PIN_MASK);
131 
132  /* Pull-up resistor, detect rising edge */
133  GPIO_DETECT_EDGE(DIMMER_SYNC_PORT_BASE, DIMMER_SYNC_PIN_MASK);
134  GPIO_TRIGGER_SINGLE_EDGE(DIMMER_SYNC_PORT_BASE, DIMMER_SYNC_PIN_MASK);
135  GPIO_DETECT_RISING(DIMMER_SYNC_PORT_BASE, DIMMER_SYNC_PIN_MASK);
136  gpio_hal_register_handler(&dimmer_handler);
137 
138  /* Spin process until an interrupt is received */
139  process_start(&ac_dimmer_int_process, NULL);
140 
141  /* Enable interrupts */
142  GPIO_ENABLE_INTERRUPT(DIMMER_SYNC_PORT_BASE, DIMMER_SYNC_PIN_MASK);
143  // ioc_set_over(DIMMER_SYNC_PORT, DIMMER_SYNC_PIN, IOC_OVERRIDE_PUE);
144  NVIC_EnableIRQ(DIMMER_INT_VECTOR);
145 
146  enabled = 1;
147  dimming = DIMMER_DEFAULT_START_VALUE;
148  return DIMMER_SUCCESS;
149  }
150 
151  /* Disable interrupt and pins */
152 
153  GPIO_DISABLE_INTERRUPT(DIMMER_SYNC_PORT_BASE, DIMMER_SYNC_PIN_MASK);
154  GPIO_SET_INPUT(DIMMER_GATE_PORT_BASE, DIMMER_GATE_PIN_MASK);
155  GPIO_SET_OUTPUT(DIMMER_SYNC_PORT_BASE, DIMMER_SYNC_PIN_MASK);
156  process_exit(&ac_dimmer_int_process);
157 
158  enabled = 0;
159  dimming = 0;
160  return DIMMER_SUCCESS;
161 }
162 /*---------------------------------------------------------------------------*/
163 SENSORS_SENSOR(ac_dimmer, AC_DIMMER_ACTUATOR, value, configure, status);
164 /*---------------------------------------------------------------------------*/
165 /** @} */
Datatype for GPIO event handlers.
Definition: gpio-hal.h:129
#define GPIO_ENABLE_INTERRUPT(PORT_BASE, PIN_MASK)
Enable interrupt triggering for pins with PIN_MASK of port with PORT_BASE.
Definition: gpio.h:201
#define PROCESS(name, strname)
Declare a process.
Definition: process.h:307
#define GPIO_SET_PIN(PORT_BASE, PIN_MASK)
Set pins with PIN_MASK of port with PORT_BASE high.
Definition: gpio.h:106
Header file for an AC light dimmer with zero-crossing driver.
#define PROCESS_YIELD_UNTIL(c)
Yield the currently running process until a condition occurs.
Definition: process.h:178
#define PROCESS_BEGIN()
Define the beginning of a process.
Definition: process.h:120
Header file with register and macro declarations for the cc2538 GPIO module.
#define GPIO_DETECT_EDGE(PORT_BASE, PIN_MASK)
Set pins with PIN_MASK of port with PORT_BASE to detect edge.
Definition: gpio.h:154
#define PROCESS_END()
Define the end of a process.
Definition: process.h:131
#define GPIO_CLR_PIN(PORT_BASE, PIN_MASK)
Set pins with PIN_MASK of port with PORT_BASE low.
Definition: gpio.h:113
Header file with declarations for the I/O Control module.
void clock_delay_usec(uint16_t dt)
Delay a given number of microseconds.
Definition: clock.c:150
#define GPIO_DETECT_RISING(PORT_BASE, PIN_MASK)
Set pins with PIN_MASK of port with PORT_BASE to trigger an interrupt on rising edge.
Definition: gpio.h:185
void process_exit(struct process *p)
Cause a process to exit.
Definition: process.c:202
void gpio_hal_register_handler(gpio_hal_event_handler_t *handler)
Register a function to be called whenever a pin triggers an event.
Definition: gpio-hal.c:55
__STATIC_INLINE void NVIC_EnableIRQ(IRQn_Type IRQn)
Enable External Interrupt.
Definition: core_cm0.h:642
#define GPIO_DISABLE_INTERRUPT(PORT_BASE, PIN_MASK)
Disable interrupt triggering for pins with PIN_MASK of port with PORT_BASE.
Definition: gpio.h:209
#define GPIO_SOFTWARE_CONTROL(PORT_BASE, PIN_MASK)
Configure the pin to be software controlled with PIN_MASK of port with PORT_BASE. ...
Definition: gpio.h:258
#define PROCESS_EXITHANDLER(handler)
Specify an action when a process exits.
Definition: process.h:254
void process_poll(struct process *p)
Request a process to be polled.
Definition: process.c:371
void ioc_set_over(uint8_t port, uint8_t pin, uint8_t over)
Set Port:Pin override function.
Definition: ioc.c:54
#define GPIO_SET_INPUT(PORT_BASE, PIN_MASK)
Set pins with PIN_MASK of port with PORT_BASE to input.
Definition: gpio.h:78
#define GPIO_SET_OUTPUT(PORT_BASE, PIN_MASK)
Set pins with PIN_MASK of port with PORT_BASE to output.
Definition: gpio.h:85
uint32_t gpio_hal_pin_mask_t
GPIO pin mask representation.
Definition: gpio-hal.h:99
#define IOC_OVERRIDE_OE
Output Enable.
Definition: ioc.h:222
#define GPIO_TRIGGER_SINGLE_EDGE(PORT_BASE, PIN_MASK)
Set pins with PIN_MASK of port with PORT_BASE to trigger an interrupt on single edge (controlled by G...
Definition: gpio.h:177
PROCESS_THREAD(cc2538_rf_process, ev, data)
Implementation of the cc2538 RF driver process.
Definition: cc2538-rf.c:1035
#define gpio_hal_pin_to_mask(pin)
Convert a pin to a pin mask.
Definition: gpio-hal.h:192
Header file for the GPIO HAL.
void process_start(struct process *p, process_data_t data)
Start a process.
Definition: process.c:99