initial revision
[ucgine.git] / examples / test-callout / main.c
1 /*
2  * Copyright 2015, Olivier MATZ <zer0@droids-corp.org>
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are met:
6  *
7  *     * Redistributions of source code must retain the above copyright
8  *       notice, this list of conditions and the following disclaimer.
9  *     * Redistributions in binary form must reproduce the above copyright
10  *       notice, this list of conditions and the following disclaimer in the
11  *       documentation and/or other materials provided with the distribution.
12  *     * Neither the name of the University of California, Berkeley nor the
13  *       names of its contributors may be used to endorse or promote products
14  *       derived from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
17  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19  * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
20  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27
28 #include <stdio.h>
29 #include <inttypes.h>
30 #include <string.h>
31
32 #include <ucg_delay.h>
33 #include <ucg_irq.h>
34 #include <ucg_callout.h>
35 #include <ucg_reent_intr.h>
36
37 static volatile uint32_t global_ms;
38 static volatile uint8_t brightness; /* 0 to 100 */
39 static volatile int8_t brightness_inc = 1;
40 static struct ucg_callout_mgr *p_intr_cm = NULL;
41
42 #if defined(UCGINE_ARCH_stm32)
43
44 #if defined(UCGINE_SUBARCH_stm32f3)
45 #include <stm32f30x.h>
46 #include <stm32f3_discovery.h>
47 #elif defined(UCGINE_SUBARCH_stm32f4)
48 #include <stm32f4xx.h>
49 #include <stm32f4_discovery.h>
50 #endif
51
52 static void target_init(void)
53 {
54         RCC_ClocksTypeDef RCC_Clocks;
55
56         /* Get SYSCLK, HCLK and PCLKx frequency */
57         RCC_GetClocksFreq(&RCC_Clocks);
58         /* generate an interrupt every ms */
59         SysTick_Config(RCC_Clocks.HCLK_Frequency / 1000);
60
61         /* Initialize LEDs */
62         STM_EVAL_LEDInit(LED6);
63 }
64
65 static void led_on(void)
66 {
67         STM_EVAL_LEDOn(LED6);
68 }
69
70 static void led_off(void)
71 {
72         STM_EVAL_LEDOff(LED6);
73 }
74
75 void reent_intr(void)
76 {
77         global_ms++;
78         if (p_intr_cm != NULL)
79                 ucg_callout_manage(p_intr_cm);
80 }
81
82 /* called every ms */
83 __attribute__ ((naked)) void SysTick_Handler(void)
84 {
85         UCG_REENT_INTR(reent_intr);
86 }
87 #elif defined(UCGINE_ARCH_avr)
88 #include <avr/io.h>
89
90 static void led_on(void)
91 {
92         PORTB |= (1 << 5);
93 }
94
95 static void led_off(void)
96 {
97         PORTB &= (~(1 << 5));
98 }
99
100 SIGNAL(TIMER0_OVF_vect)
101 {
102         static uint16_t i = 0;
103
104         i++;
105         if ((i & 0x3) != 0)
106                 return;
107
108         global_ms++;
109         if (p_intr_cm != NULL)
110                 ucg_callout_manage(p_intr_cm);
111 }
112
113 static void target_init(void)
114 {
115         DDRB = (1 << 5);
116
117         TCCR0B = (1 << CS01);   /* div = 8 */
118         TIMSK0 |= (1 << TOIE0); /* enable timer0 intr */
119 }
120 #endif
121
122 static uint16_t get_time_ms(void)
123 {
124         ucg_irqflags_t flags;
125         uint32_t ms;
126
127         flags = ucg_irq_lock_save();
128         ms = global_ms;
129         ucg_irq_unlock_restore(flags);
130         return ms;
131 }
132
133 /* every ms, enable or disable the led depending on brightness */
134 static void led_control_cb(struct ucg_callout_mgr *cm,
135         struct ucg_callout *tim, void *arg)
136 {
137         static uint8_t accu;
138
139         (void)arg;
140
141         accu += brightness;
142         if (accu < 100) {
143                 led_off();
144         } else {
145                 led_on();
146                 accu -= 100;
147         }
148
149         ucg_callout_reschedule(cm, tim, 1);
150 }
151
152 /* every 50 ms, change increase or decrease the brightness from 0 to 100 */
153 static void led_update_brightness_cb(struct ucg_callout_mgr *cm,
154         struct ucg_callout *tim, void *arg)
155 {
156         (void)arg;
157
158         brightness += brightness_inc;
159         if (brightness == 0)
160                 brightness_inc = 1;
161         else if (brightness == 100)
162                 brightness_inc = -1;
163
164         ucg_callout_reschedule(cm, tim, 10);
165 }
166
167 /* every second, sleep during 100ms */
168 static void sleep_cb(struct ucg_callout_mgr *cm,
169         struct ucg_callout *tim, void *arg)
170 {
171         (void)arg;
172
173         ucg_delay_ms(200);
174         ucg_callout_reschedule(cm, tim, 300);
175 }
176
177 int main(void)
178 {
179         struct ucg_callout_mgr intr_cm;
180         struct ucg_callout_mgr loop_cm;
181         struct ucg_callout br_timer;
182         struct ucg_callout led_timer;
183         struct ucg_callout sleep_timer;
184         int i;
185
186         target_init();
187
188         /* toggle the pin before starting */
189         for (i = 0; i < 3; i++) {
190                 ucg_delay_ms(500);
191                 ucg_delay_ms(500);
192         }
193
194         /* init loop callout manager */
195         ucg_callout_mgr_init(&loop_cm, get_time_ms);
196
197         /* load a timer in the loop cmgr that will update the brightness */
198         ucg_callout_init(&br_timer, led_update_brightness_cb, NULL, 128);
199         ucg_callout_schedule(&loop_cm, &br_timer, 0);
200
201         /* init intr callout manager */
202         ucg_callout_mgr_init(&intr_cm, get_time_ms);
203         ucg_irq_lock();
204         p_intr_cm = &intr_cm;
205         ucg_irq_unlock();
206
207         /* load a timer in the intr cmgr that control led on/off */
208         ucg_callout_init(&led_timer, led_control_cb, NULL, 128);
209         ucg_callout_schedule(&intr_cm, &led_timer, 0);
210
211         /* load a lower prio timer in the intr cmgr that just sleeps */
212         ucg_callout_init(&sleep_timer, sleep_cb, NULL, 100);
213         ucg_callout_schedule(&intr_cm, &sleep_timer, 0);
214
215         while (1) {
216                 ucg_callout_manage(&loop_cm);
217         }
218
219         while (1);
220         return 0;
221 }