xref: /btstack/port/samv71-xplained-atwilc3000/main.c (revision 1b2596b5303dd8caeea8565532c93cca8dab8cc4)
1 /**
2  * \file
3  *
4  * \brief Getting Started Application.
5  *
6  * Copyright (c) 2011-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 /**
45  * \mainpage Getting Started Application
46  *
47  * \section Purpose
48  *
49  * The Getting Started example will help new users get familiar with Atmel's
50  * SAM family of microcontrollers. This basic application shows the startup
51  * sequence of a chip and how to use its core peripherals.
52  *
53  * \section Requirements
54  *
55  * This package can be used with SAM evaluation kits.
56  *
57  * \section Description
58  *
59  * The demonstration program makes the LED(s) on the board blink at a fixed rate.
60  * This rate is generated by using Time tick timer. The blinking can be stopped
61  * using the push button.
62  *
63  * \section Usage
64  *
65  * -# Build the program and download it inside the evaluation board.
66  * -# On the computer, open and configure a terminal application
67  *    (e.g. HyperTerminal on Microsoft Windows) with these settings:
68  *   - 115200 bauds
69  *   - 8 bits of data
70  *   - No parity
71  *   - 1 stop bit
72  *   - No flow control
73  * -# Start the application.
74  * -# The LED(s) should start blinking on the board. In the terminal window, the
75  *    following text should appear (values depend on the board and chip used):
76  *    \code
77 	-- Getting Started Example xxx --
78 	-- xxxxxx-xx
79 	-- Compiled: xxx xx xxxx xx:xx:xx --
80 \endcode
81  * -# Pressing and release button 1 should make one LED stop & restart
82  *    blinking.
83  * -# If the button 2 available, pressing button 2 should make the other LED
84  *    stop & restart blinking.
85  *
86  */
87 /*
88  * Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
89  */
90 
91 #include "asf.h"
92 #include "stdio_serial.h"
93 #include "conf_board.h"
94 #include "conf_clock.h"
95 
96 /** IRQ priority for PIO (The lower the value, the greater the priority) */
97 // [main_def_pio_irq_prior]
98 #define IRQ_PRIOR_PIO    0
99 // [main_def_pio_irq_prior]
100 
101 /** LED0 blink time, LED1 blink half this time, in ms */
102 #define BLINK_PERIOD     1000
103 
104 #define STRING_EOL    "\r"
105 #define STRING_HEADER "-- Getting Started Example --\r\n" \
106 		"-- "BOARD_NAME" --\r\n" \
107 		"-- Compiled: "__DATE__" "__TIME__" --"STRING_EOL
108 
109 /** LED0 blinking control. */
110 // [main_var_led0_control]
111 volatile bool g_b_led0_active = true;
112 // [main_var_led0_control]
113 
114 #ifdef LED1_GPIO
115 /** LED1 blinking control. */
116 // [main_var_led1_control]
117 volatile bool g_b_led1_active = true;
118 // [main_var_led1_control]
119 #endif
120 
121 /** Global g_ul_ms_ticks in milliseconds since start of application */
122 // [main_var_ticks]
123 volatile uint32_t g_ul_ms_ticks = 0;
124 // [main_var_ticks]
125 
126 /// @cond 0
127 /**INDENT-OFF**/
128 #ifdef __cplusplus
129 extern "C" {
130 #endif
131 /**INDENT-ON**/
132 /// @endcond
133 
134 /**
135  *  \brief Process Buttons Events
136  *
137  *  Change active states of LEDs when corresponding button events happened.
138  */
139 static void ProcessButtonEvt(uint8_t uc_button)
140 {
141 // [main_button1_evnt_process]
142 	if (uc_button == 0) {
143 		g_b_led0_active = !g_b_led0_active;
144 		if (!g_b_led0_active) {
145 			ioport_set_pin_level(LED0_GPIO, IOPORT_PIN_LEVEL_HIGH);
146 		}
147 	}
148 // [main_button1_evnt_process]
149 #ifdef LED1_GPIO
150 	else {
151 // [main_button2_evnt_process]
152 		g_b_led1_active = !g_b_led1_active;
153 
154 		/* Enable LED#2 and TC if they were enabled */
155 		if (g_b_led1_active) {
156 			ioport_set_pin_level(LED1_GPIO, IOPORT_PIN_LEVEL_LOW);
157 			tc_start(TC0, 0);
158 		}
159 		/* Disable LED#2 and TC if they were disabled */
160 		else {
161 			ioport_set_pin_level(LED1_GPIO, IOPORT_PIN_LEVEL_HIGH);
162 			tc_stop(TC0, 0);
163 		}
164 // [main_button2_evnt_process]
165 	}
166 #endif
167 }
168 
169 /**
170  *  \brief Handler for System Tick interrupt.
171  *
172  *  Process System Tick Event
173  *  Increments the g_ul_ms_ticks counter.
174  */
175 // [main_systick_handler]
176 void SysTick_Handler(void)
177 {
178 	g_ul_ms_ticks++;
179 }
180 // [main_systick_handler]
181 
182 /**
183  *  \brief Handler for Button 1 rising edge interrupt.
184  *
185  *  Handle process led1 status change.
186  */
187 // [main_button1_handler]
188 static void Button1_Handler(uint32_t id, uint32_t mask)
189 {
190 	if (PIN_PUSHBUTTON_1_ID == id && PIN_PUSHBUTTON_1_MASK == mask) {
191 		ProcessButtonEvt(0);
192 	}
193 }
194 // [main_button1_handler]
195 
196 #ifndef BOARD_NO_PUSHBUTTON_2
197 /**
198  *  \brief Handler for Button 2 falling edge interrupt.
199  *
200  *  Handle process led2 status change.
201  */
202 // [main_button2_handler]
203 static void Button2_Handler(uint32_t id, uint32_t mask)
204 {
205 	if (PIN_PUSHBUTTON_2_ID == id && PIN_PUSHBUTTON_2_MASK == mask) {
206 		ProcessButtonEvt(1);
207 	}
208 }
209 // [main_button2_handler]
210 #endif
211 
212 /**
213  *  \brief Configure the Pushbuttons
214  *
215  *  Configure the PIO as inputs and generate corresponding interrupt when
216  *  pressed or released.
217  */
218 static void configure_buttons(void)
219 {
220 // [main_button1_configure]
221 	/* Configure Pushbutton 1 */
222 	pmc_enable_periph_clk(PIN_PUSHBUTTON_1_ID);
223 	pio_set_debounce_filter(PIN_PUSHBUTTON_1_PIO, PIN_PUSHBUTTON_1_MASK, 10);
224 	/* Interrupt on rising edge  */
225 	pio_handler_set(PIN_PUSHBUTTON_1_PIO, PIN_PUSHBUTTON_1_ID,
226 			PIN_PUSHBUTTON_1_MASK, PIN_PUSHBUTTON_1_ATTR, Button1_Handler);
227 	NVIC_EnableIRQ((IRQn_Type) PIN_PUSHBUTTON_1_ID);
228 	pio_handler_set_priority(PIN_PUSHBUTTON_1_PIO,
229 			(IRQn_Type) PIN_PUSHBUTTON_1_ID, IRQ_PRIOR_PIO);
230 	pio_enable_interrupt(PIN_PUSHBUTTON_1_PIO, PIN_PUSHBUTTON_1_MASK);
231 // [main_button1_configure]
232 #ifndef BOARD_NO_PUSHBUTTON_2
233 // [main_button2_configure]
234 	/* Configure Pushbutton 2 */
235 	pmc_enable_periph_clk(PIN_PUSHBUTTON_2_ID);
236 	pio_set_debounce_filter(PIN_PUSHBUTTON_2_PIO, PIN_PUSHBUTTON_2_MASK, 10);
237 	/* Interrupt on falling edge */
238 	pio_handler_set(PIN_PUSHBUTTON_2_PIO, PIN_PUSHBUTTON_2_ID,
239 			PIN_PUSHBUTTON_2_MASK, PIN_PUSHBUTTON_2_ATTR, Button2_Handler);
240 	NVIC_EnableIRQ((IRQn_Type) PIN_PUSHBUTTON_2_ID);
241 	pio_handler_set_priority(PIN_PUSHBUTTON_2_PIO,
242 			(IRQn_Type) PIN_PUSHBUTTON_2_ID, IRQ_PRIOR_PIO);
243 	pio_enable_interrupt(PIN_PUSHBUTTON_2_PIO, PIN_PUSHBUTTON_2_MASK);
244 // [main_button2_configure]
245 #endif
246 }
247 
248 /**
249  *  Interrupt handler for TC0 interrupt. Toggles the state of LED\#2.
250  */
251 // [main_tc0_handler]
252 #ifndef BOARD_NO_LED_1
253 void TC0_Handler(void)
254 {
255 	volatile uint32_t ul_dummy;
256 
257 	/* Clear status bit to acknowledge interrupt */
258 	ul_dummy = tc_get_status(TC0, 0);
259 
260 	/* Avoid compiler warning */
261 	UNUSED(ul_dummy);
262 
263 #ifdef LED1_GPIO
264 	/** Toggle LED state. */
265 	ioport_toggle_pin_level(LED1_GPIO);
266 #endif
267 
268 	printf("2 ");
269 }
270 // [main_tc0_handler]
271 
272 /**
273  *  Configure Timer Counter 0 to generate an interrupt every 250ms.
274  */
275 // [main_tc_configure]
276 static void configure_tc(void)
277 {
278 	uint32_t ul_div;
279 	uint32_t ul_tcclks;
280 	uint32_t ul_sysclk = sysclk_get_cpu_hz();
281 
282 	/* Configure PMC */
283 	pmc_enable_periph_clk(ID_TC0);
284 #if SAMG55
285 	/* Enable PCK output */
286 	pmc_disable_pck(PMC_PCK_3);
287 	pmc_switch_pck_to_sclk(PMC_PCK_3, PMC_PCK_PRES(0));
288 	pmc_enable_pck(PMC_PCK_3);
289 #endif
290 
291 	/** Configure TC for a 4Hz frequency and trigger on RC compare. */
292 	tc_find_mck_divisor(4, ul_sysclk, &ul_div, &ul_tcclks, ul_sysclk);
293 	tc_init(TC0, 0, ul_tcclks | TC_CMR_CPCTRG);
294 	tc_write_rc(TC0, 0, (ul_sysclk / ul_div) / 4);
295 
296 	/* Configure and enable interrupt on RC compare */
297 	NVIC_EnableIRQ((IRQn_Type) ID_TC0);
298 	tc_enable_interrupt(TC0, 0, TC_IER_CPCS);
299 
300 #ifdef LED1_GPIO
301 	/** Start the counter if LED1 is enabled. */
302 	if (g_b_led1_active) {
303 		tc_start(TC0, 0);
304 	}
305 #else
306 	tc_start(TC0, 0);
307 #endif
308 }
309 #endif
310 // [main_tc_configure]
311 
312 /**
313  *  Configure UART console.
314  */
315 // [main_console_configure]
316 static void configure_console(void)
317 {
318 	const usart_serial_options_t uart_serial_options = {
319 		.baudrate = CONF_UART_BAUDRATE,
320 #ifdef CONF_UART_CHAR_LENGTH
321 		.charlength = CONF_UART_CHAR_LENGTH,
322 #endif
323 		.paritytype = CONF_UART_PARITY,
324 #ifdef CONF_UART_STOP_BITS
325 		.stopbits = CONF_UART_STOP_BITS,
326 #endif
327 	};
328 
329 	/* Configure console UART. */
330 	sysclk_enable_peripheral_clock(CONSOLE_UART_ID);
331 	stdio_serial_init(CONF_UART, &uart_serial_options);
332 }
333 
334 // [main_console_configure]
335 
336 /**
337  * \brief Wait for the given number of milliseconds (using the g_ul_ms_ticks
338  * generated by the SAM's microcontrollers's system tick).
339  *
340  * \param ul_dly_ticks  Delay to wait for, in milliseconds.
341  */
342 // [main_ms_delay]
343 static void mdelay(uint32_t ul_dly_ticks)
344 {
345 	uint32_t ul_cur_ticks;
346 
347 	ul_cur_ticks = g_ul_ms_ticks;
348 	while ((g_ul_ms_ticks - ul_cur_ticks) < ul_dly_ticks);
349 }
350 // [main_ms_delay]
351 
352 /**
353  *  \brief getting-started Application entry point.
354  *
355  *  \return Unused (ANSI-C compatibility).
356  */
357 // [main]
358 int main(void)
359 {
360 //! [main_step_sys_init]
361 	/* Initialize the SAM system */
362 	sysclk_init();
363 	board_init();
364 //! [main_step_sys_init]
365 
366 #ifndef BOARD_NO_PUSHBUTTON_2
367 #if (SAMV71 || SAMV70 || SAMS70 || SAME70)
368 	if (GPIO_PUSH_BUTTON_2 == PIO_PB12_IDX) {
369 		matrix_set_system_io(matrix_get_system_io() | CCFG_SYSIO_SYSIO12);
370 	}
371 	ioport_set_pin_dir(GPIO_PUSH_BUTTON_2, IOPORT_DIR_INPUT);
372 	ioport_set_pin_mode(GPIO_PUSH_BUTTON_2, GPIO_PUSH_BUTTON_2_FLAGS);
373 	ioport_set_pin_sense_mode(GPIO_PUSH_BUTTON_2, GPIO_PUSH_BUTTON_2_SENSE);
374 #endif
375 #endif
376 //! [main_step_console_init]
377 	/* Initialize the console uart */
378 	configure_console();
379 //! [main_step_console_init]
380 
381 	/* Output example information */
382 	puts(STRING_HEADER);
383 
384 	/* Configure systick for 1 ms */
385 	puts("Configure system tick to get 1ms tick period.\r");
386 //! [main_step_systick_init]
387 	if (SysTick_Config(sysclk_get_cpu_hz() / 1000)) {
388 		puts("-F- Systick configuration error\r");
389 		while (1);
390 	}
391 //! [main_step_systick_init]
392 
393 #ifndef BOARD_NO_LED_1
394 	puts("Configure TC.\r");
395 //! [main_step_tc_init]
396 	configure_tc();
397 //! [main_step_tc_init]
398 #endif
399 
400 	puts("Configure buttons with debouncing.\r");
401 //! [main_step_btn_init]
402 	configure_buttons();
403 //! [main_step_btn_init]
404 
405 	printf("Press %s to Start/Stop the %s blinking.\r\n",
406 			PUSHBUTTON_1_NAME, LED_0_NAME);
407 
408 #ifndef BOARD_NO_PUSHBUTTON_2
409 	printf("Press %s to Start/Stop the %s blinking.\r\n",
410 			PUSHBUTTON_2_NAME, LED_1_NAME);
411 #endif
412 
413 //! [main_step_loop]
414 	while (1) {
415 		/* Wait for LED to be active */
416 		while (!g_b_led0_active);
417 
418 		/* Toggle LED state if active */
419 		if (g_b_led0_active) {
420 			ioport_toggle_pin_level(LED0_GPIO);
421 			printf("1 ");
422 		}
423 
424 		/* Wait for 500ms */
425 		mdelay(300);
426 	}
427 //! [main_step_loop]
428 }
429 // [main]
430 /// @cond 0
431 /**INDENT-OFF**/
432 #ifdef __cplusplus
433 }
434 #endif
435 /**INDENT-ON**/
436 /// @endcond
437