Full graphic 640x400 monochrome VGA driver library
vga640x400g.c@0:ca7defdc9e44, 2011-07-24 (annotated)
- Committer:
- gertk
- Date:
- Sun Jul 24 11:53:05 2011 +0000
- Revision:
- 0:ca7defdc9e44
version 0.1
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
gertk | 0:ca7defdc9e44 | 1 | /* |
gertk | 0:ca7defdc9e44 | 2 | * 640x400 70Hz full graphic VGA Driver |
gertk | 0:ca7defdc9e44 | 3 | * |
gertk | 0:ca7defdc9e44 | 4 | * Copyright (C) 2011 by Ivo van Poorten <ivop(at)euronet.nl> |
gertk | 0:ca7defdc9e44 | 5 | * and Gert van der Knokke <gertk(at)xs4all.nl> |
gertk | 0:ca7defdc9e44 | 6 | * This file is licensed under the terms of the GNU Lesser |
gertk | 0:ca7defdc9e44 | 7 | * General Public License, version 3. |
gertk | 0:ca7defdc9e44 | 8 | * |
gertk | 0:ca7defdc9e44 | 9 | * Inspired by Simon's (not Ford) Cookbook entry and Cliff Biffle's |
gertk | 0:ca7defdc9e44 | 10 | * assembly code. |
gertk | 0:ca7defdc9e44 | 11 | */ |
gertk | 0:ca7defdc9e44 | 12 | #include "fastlib/common.h" |
gertk | 0:ca7defdc9e44 | 13 | #include "fastlib/pinsel.h" |
gertk | 0:ca7defdc9e44 | 14 | #include "fastlib/gpio.h" |
gertk | 0:ca7defdc9e44 | 15 | #include "fastlib/clock.h" |
gertk | 0:ca7defdc9e44 | 16 | #include "fastlib/power.h" |
gertk | 0:ca7defdc9e44 | 17 | #include "fastlib/pwm.h" |
gertk | 0:ca7defdc9e44 | 18 | #include "fastlib/i2s.h" |
gertk | 0:ca7defdc9e44 | 19 | #include "fastlib/uart.h" |
gertk | 0:ca7defdc9e44 | 20 | #include "fastlib/dma.h" |
gertk | 0:ca7defdc9e44 | 21 | #include "fastlib/nvic.h" |
gertk | 0:ca7defdc9e44 | 22 | #include "vga640x400g_functions.h" |
gertk | 0:ca7defdc9e44 | 23 | |
gertk | 0:ca7defdc9e44 | 24 | |
gertk | 0:ca7defdc9e44 | 25 | // ----------------------------------------------------------------------------------- |
gertk | 0:ca7defdc9e44 | 26 | |
gertk | 0:ca7defdc9e44 | 27 | // force the framebuffer in ABSHRAM0 and ABSHRAM1 (16k + 16k) |
gertk | 0:ca7defdc9e44 | 28 | // warning!! this disables the use of the USB, Ethernet and CAN bus functions! |
gertk | 0:ca7defdc9e44 | 29 | unsigned char *framebuffer = (unsigned char *)(0x2007C000); |
gertk | 0:ca7defdc9e44 | 30 | |
gertk | 0:ca7defdc9e44 | 31 | // the framepointer |
gertk | 0:ca7defdc9e44 | 32 | volatile unsigned char *pointer=framebuffer; |
gertk | 0:ca7defdc9e44 | 33 | |
gertk | 0:ca7defdc9e44 | 34 | // active line counter |
gertk | 0:ca7defdc9e44 | 35 | static unsigned line_counter; |
gertk | 0:ca7defdc9e44 | 36 | |
gertk | 0:ca7defdc9e44 | 37 | // ----------------------------------------------------------------------------------- |
gertk | 0:ca7defdc9e44 | 38 | // setup CPU PLL |
gertk | 0:ca7defdc9e44 | 39 | #define FEED0_AND_WAIT(x,y) fl_pll0_feed(); while(y fl_pll0_get_##x()) |
gertk | 0:ca7defdc9e44 | 40 | |
gertk | 0:ca7defdc9e44 | 41 | static void init_pll0(unsigned int clock_source, int N, int M, int cpu_divider) { |
gertk | 0:ca7defdc9e44 | 42 | fl_select_pll0_clock_source(clock_source); |
gertk | 0:ca7defdc9e44 | 43 | |
gertk | 0:ca7defdc9e44 | 44 | fl_pll0_control(FL_ENABLE, FL_DISCONNECT); |
gertk | 0:ca7defdc9e44 | 45 | FEED0_AND_WAIT(connect,); |
gertk | 0:ca7defdc9e44 | 46 | fl_pll0_control(FL_DISABLE, FL_DISCONNECT); |
gertk | 0:ca7defdc9e44 | 47 | FEED0_AND_WAIT(enable,); |
gertk | 0:ca7defdc9e44 | 48 | |
gertk | 0:ca7defdc9e44 | 49 | fl_pll0_config(N, M); |
gertk | 0:ca7defdc9e44 | 50 | fl_pll0_feed(); |
gertk | 0:ca7defdc9e44 | 51 | |
gertk | 0:ca7defdc9e44 | 52 | fl_pll0_control(FL_ENABLE, FL_DISCONNECT); |
gertk | 0:ca7defdc9e44 | 53 | FEED0_AND_WAIT(enable,!); |
gertk | 0:ca7defdc9e44 | 54 | |
gertk | 0:ca7defdc9e44 | 55 | fl_set_cpu_clock_divider(cpu_divider); |
gertk | 0:ca7defdc9e44 | 56 | while (!fl_pll0_get_lock()) ; |
gertk | 0:ca7defdc9e44 | 57 | |
gertk | 0:ca7defdc9e44 | 58 | fl_pll0_control(FL_ENABLE, FL_CONNECT); |
gertk | 0:ca7defdc9e44 | 59 | FEED0_AND_WAIT(connect,!); |
gertk | 0:ca7defdc9e44 | 60 | } |
gertk | 0:ca7defdc9e44 | 61 | |
gertk | 0:ca7defdc9e44 | 62 | // ----------------------------------------------------------------------------------- |
gertk | 0:ca7defdc9e44 | 63 | // setup UART0 |
gertk | 0:ca7defdc9e44 | 64 | static void init_uart0(unsigned divaddval, unsigned mulval, unsigned divisor) { |
gertk | 0:ca7defdc9e44 | 65 | fl_power_uart0(FL_ON); |
gertk | 0:ca7defdc9e44 | 66 | fl_select_clock_uart0(FL_CLOCK_DIV1); |
gertk | 0:ca7defdc9e44 | 67 | fl_uart_set_fractional_divider(0, divaddval, mulval); |
gertk | 0:ca7defdc9e44 | 68 | fl_uart_set_divisor_latch(0, divisor); |
gertk | 0:ca7defdc9e44 | 69 | } |
gertk | 0:ca7defdc9e44 | 70 | |
gertk | 0:ca7defdc9e44 | 71 | // ----------------------------------------------------------------------------------- |
gertk | 0:ca7defdc9e44 | 72 | // setup VSYNC output on designated pin |
gertk | 0:ca7defdc9e44 | 73 | static void init_vsync(unsigned port, unsigned pin) { |
gertk | 0:ca7defdc9e44 | 74 | fl_power_gpio(FL_ON); |
gertk | 0:ca7defdc9e44 | 75 | fl_pinsel(port, pin, FL_FUNC_DEFAULT, FL_IGNORE, FL_IGNORE); |
gertk | 0:ca7defdc9e44 | 76 | fl_gpio_set_direction(port, 1<<pin, FL_OUTPUT); |
gertk | 0:ca7defdc9e44 | 77 | fl_gpio_clear_value (port, 1<<pin); |
gertk | 0:ca7defdc9e44 | 78 | } |
gertk | 0:ca7defdc9e44 | 79 | |
gertk | 0:ca7defdc9e44 | 80 | // ----------------------------------------------------------------------------------- |
gertk | 0:ca7defdc9e44 | 81 | // define structure for DMA linked lists |
gertk | 0:ca7defdc9e44 | 82 | struct dma_lli { |
gertk | 0:ca7defdc9e44 | 83 | void *source; |
gertk | 0:ca7defdc9e44 | 84 | void *dest; |
gertk | 0:ca7defdc9e44 | 85 | struct dma_lli *next; |
gertk | 0:ca7defdc9e44 | 86 | unsigned control_word; |
gertk | 0:ca7defdc9e44 | 87 | }; |
gertk | 0:ca7defdc9e44 | 88 | |
gertk | 0:ca7defdc9e44 | 89 | // some arbitrary blank data for I2S used for blanking |
gertk | 0:ca7defdc9e44 | 90 | // even after DMA the I2S output will keep on emitting zeroes (= blank) |
gertk | 0:ca7defdc9e44 | 91 | static unsigned char blanking[32]={0,0,0,0,0,0,0,0, |
gertk | 0:ca7defdc9e44 | 92 | 0,0,0,0,0,0,0,0, |
gertk | 0:ca7defdc9e44 | 93 | 0,0,0,0,0,0,0,0, |
gertk | 0:ca7defdc9e44 | 94 | 0,0,0,0,0,0,0,0 |
gertk | 0:ca7defdc9e44 | 95 | }; |
gertk | 0:ca7defdc9e44 | 96 | |
gertk | 0:ca7defdc9e44 | 97 | // preset our blanking DMA linked list |
gertk | 0:ca7defdc9e44 | 98 | extern const struct dma_lli blank_lli; |
gertk | 0:ca7defdc9e44 | 99 | |
gertk | 0:ca7defdc9e44 | 100 | // blank linked lists ends the DMA cycle (lli=0) |
gertk | 0:ca7defdc9e44 | 101 | static const struct dma_lli blank_lli = { |
gertk | 0:ca7defdc9e44 | 102 | blanking, (void*)FL_I2STXFIFO, 0, 4 |
gertk | 0:ca7defdc9e44 | 103 | | (1 << 12) |
gertk | 0:ca7defdc9e44 | 104 | | (1 << 15) |
gertk | 0:ca7defdc9e44 | 105 | | (2 << 18) |
gertk | 0:ca7defdc9e44 | 106 | | (2 << 21) |
gertk | 0:ca7defdc9e44 | 107 | | (0 << 26) |
gertk | 0:ca7defdc9e44 | 108 | | (0 << 27) |
gertk | 0:ca7defdc9e44 | 109 | | (0 << 31) |
gertk | 0:ca7defdc9e44 | 110 | }; |
gertk | 0:ca7defdc9e44 | 111 | |
gertk | 0:ca7defdc9e44 | 112 | // setup the DMA controller |
gertk | 0:ca7defdc9e44 | 113 | static void init_dma_controller(void) { |
gertk | 0:ca7defdc9e44 | 114 | fl_power_gpdma(FL_ON); |
gertk | 0:ca7defdc9e44 | 115 | fl_dma_enable(FL_ENABLE); |
gertk | 0:ca7defdc9e44 | 116 | while (!fl_dma_is_enabled()) ; |
gertk | 0:ca7defdc9e44 | 117 | |
gertk | 0:ca7defdc9e44 | 118 | // do some initial DMA setup but no need to start the DMA |
gertk | 0:ca7defdc9e44 | 119 | fl_dma_set_srcaddr (0, framebuffer); // initial source pointer |
gertk | 0:ca7defdc9e44 | 120 | fl_dma_set_destaddr(0, (void*)FL_I2STXFIFO); // destination is I2S |
gertk | 0:ca7defdc9e44 | 121 | fl_dma_set_next_lli(0, &blank_lli); // link active list to blank list |
gertk | 0:ca7defdc9e44 | 122 | |
gertk | 0:ca7defdc9e44 | 123 | fl_dma_channel_control(0, // control word |
gertk | 0:ca7defdc9e44 | 124 | 20, // count (20*4 = 80) |
gertk | 0:ca7defdc9e44 | 125 | 4, 4, // src and dest burst size |
gertk | 0:ca7defdc9e44 | 126 | 32, 32, // src and dest width |
gertk | 0:ca7defdc9e44 | 127 | FL_SRC_INCREMENT, |
gertk | 0:ca7defdc9e44 | 128 | FL_NO_DEST_INCREMENT, |
gertk | 0:ca7defdc9e44 | 129 | FL_OFF // no interrupts |
gertk | 0:ca7defdc9e44 | 130 | ); |
gertk | 0:ca7defdc9e44 | 131 | |
gertk | 0:ca7defdc9e44 | 132 | } |
gertk | 0:ca7defdc9e44 | 133 | |
gertk | 0:ca7defdc9e44 | 134 | // ----------------------------------------------------------------------------------- |
gertk | 0:ca7defdc9e44 | 135 | // setup I2S for 25 MHz dot/pixel clock |
gertk | 0:ca7defdc9e44 | 136 | static void init_i2s(void) { |
gertk | 0:ca7defdc9e44 | 137 | // I2S on P0.9 (DIP5) |
gertk | 0:ca7defdc9e44 | 138 | fl_power_i2s(FL_ON); |
gertk | 0:ca7defdc9e44 | 139 | fl_select_clock_i2s(FL_CLOCK_DIV1); // assume 100MHz |
gertk | 0:ca7defdc9e44 | 140 | fl_pinsel(0, 7, FL_FUNC_ALT1, FL_IGNORE, FL_IGNORE); // I2STX_CLK |
gertk | 0:ca7defdc9e44 | 141 | fl_pinsel(0, 8, FL_FUNC_ALT1, FL_IGNORE, FL_IGNORE); // I2STX_WS |
gertk | 0:ca7defdc9e44 | 142 | fl_pinsel(0, 9, FL_FUNC_ALT1, FL_IGNORE, FL_IGNORE); // I2STX_SDA |
gertk | 0:ca7defdc9e44 | 143 | fl_i2s_set_tx_rate(1, 4); |
gertk | 0:ca7defdc9e44 | 144 | fl_i2s_output_set_config(FL_8BITS, FL_STEREO, 8, 0, 0, 0, 0); |
gertk | 0:ca7defdc9e44 | 145 | |
gertk | 0:ca7defdc9e44 | 146 | } |
gertk | 0:ca7defdc9e44 | 147 | |
gertk | 0:ca7defdc9e44 | 148 | // ----------------------------------------------------------------------------------- |
gertk | 0:ca7defdc9e44 | 149 | // create HSYNC output with PWM |
gertk | 0:ca7defdc9e44 | 150 | static void init_hsync(void) { |
gertk | 0:ca7defdc9e44 | 151 | // PWM1.2 on P2.1 (DIP25) |
gertk | 0:ca7defdc9e44 | 152 | fl_power_pwm1(FL_ON); |
gertk | 0:ca7defdc9e44 | 153 | fl_select_clock_pwm1(FL_CLOCK_DIV1); |
gertk | 0:ca7defdc9e44 | 154 | fl_pinsel(2, 1, FL_FUNC_ALT1, FL_FLOATING, FL_FLOATING); // PWM1.2, no pullup/down |
gertk | 0:ca7defdc9e44 | 155 | fl_pwm_set_prescale(4); // 100/25 = 4 |
gertk | 0:ca7defdc9e44 | 156 | |
gertk | 0:ca7defdc9e44 | 157 | #define HSHIFT 0 |
gertk | 0:ca7defdc9e44 | 158 | |
gertk | 0:ca7defdc9e44 | 159 | // main PWM |
gertk | 0:ca7defdc9e44 | 160 | fl_pwm_set_match(0, 800); // 800 color clocks |
gertk | 0:ca7defdc9e44 | 161 | |
gertk | 0:ca7defdc9e44 | 162 | // generate line interrupts from PWM MR0 |
gertk | 0:ca7defdc9e44 | 163 | fl_pwm_config_match(0, FL_ON, FL_ON, FL_OFF); // interrupt, reset, !stop |
gertk | 0:ca7defdc9e44 | 164 | |
gertk | 0:ca7defdc9e44 | 165 | // this PWM generates the HSYNC pulse |
gertk | 0:ca7defdc9e44 | 166 | fl_pwm_set_match(2, 16+HSHIFT); // go low at 16 |
gertk | 0:ca7defdc9e44 | 167 | fl_pwm_set_match(1, 48+HSHIFT); // go high at 48 |
gertk | 0:ca7defdc9e44 | 168 | fl_pwm_config_edges(2, FL_DOUBLE_EDGE); // need this for negative sync |
gertk | 0:ca7defdc9e44 | 169 | fl_pwm_output_enable(2, FL_ENABLE); // enable this output |
gertk | 0:ca7defdc9e44 | 170 | |
gertk | 0:ca7defdc9e44 | 171 | } |
gertk | 0:ca7defdc9e44 | 172 | |
gertk | 0:ca7defdc9e44 | 173 | // ----------------------------------------------------------------------------------- |
gertk | 0:ca7defdc9e44 | 174 | // state machine list for the complete screen output |
gertk | 0:ca7defdc9e44 | 175 | static void state_before_vsync(void); |
gertk | 0:ca7defdc9e44 | 176 | |
gertk | 0:ca7defdc9e44 | 177 | static void (*state)(void) = state_before_vsync; |
gertk | 0:ca7defdc9e44 | 178 | |
gertk | 0:ca7defdc9e44 | 179 | static void state_blank_area(void) { |
gertk | 0:ca7defdc9e44 | 180 | if (line_counter != 449) return; |
gertk | 0:ca7defdc9e44 | 181 | |
gertk | 0:ca7defdc9e44 | 182 | line_counter = 0; |
gertk | 0:ca7defdc9e44 | 183 | pointer=framebuffer; |
gertk | 0:ca7defdc9e44 | 184 | state = state_before_vsync; |
gertk | 0:ca7defdc9e44 | 185 | } |
gertk | 0:ca7defdc9e44 | 186 | |
gertk | 0:ca7defdc9e44 | 187 | |
gertk | 0:ca7defdc9e44 | 188 | // emit a line from the visible area (framebuffer) |
gertk | 0:ca7defdc9e44 | 189 | static void state_visible_area(void) { |
gertk | 0:ca7defdc9e44 | 190 | extern const struct dma_lli blank_lli; |
gertk | 0:ca7defdc9e44 | 191 | |
gertk | 0:ca7defdc9e44 | 192 | if (line_counter != 438) { |
gertk | 0:ca7defdc9e44 | 193 | // reset DMA parameters for active line |
gertk | 0:ca7defdc9e44 | 194 | fl_dma_set_srcaddr (0,(unsigned char *)pointer); // source is our current framebuffer pointer |
gertk | 0:ca7defdc9e44 | 195 | fl_dma_set_destaddr(0, (void*)FL_I2STXFIFO); // destination is I2S |
gertk | 0:ca7defdc9e44 | 196 | fl_dma_set_next_lli(0, &blank_lli); // connect to blanking list |
gertk | 0:ca7defdc9e44 | 197 | fl_dma_channel_control(0, // control word |
gertk | 0:ca7defdc9e44 | 198 | 20, // count (20*4 = 80 bytes active) |
gertk | 0:ca7defdc9e44 | 199 | 4, 4, // src and dest burst size |
gertk | 0:ca7defdc9e44 | 200 | 32, 32, // src and dest width |
gertk | 0:ca7defdc9e44 | 201 | FL_SRC_INCREMENT, |
gertk | 0:ca7defdc9e44 | 202 | FL_NO_DEST_INCREMENT, |
gertk | 0:ca7defdc9e44 | 203 | FL_OFF // no interrupt on first 640 pixel |
gertk | 0:ca7defdc9e44 | 204 | ); |
gertk | 0:ca7defdc9e44 | 205 | // restart DMA sequence |
gertk | 0:ca7defdc9e44 | 206 | fl_dma_channel_config(0, FL_ENABLE, |
gertk | 0:ca7defdc9e44 | 207 | FL_DMA_PERIPHERAL_IS_MEMORY, FL_DMA_BURST_REQUEST_I2S_CH0, |
gertk | 0:ca7defdc9e44 | 208 | FL_DMA_MEMORY_TO_PERIPHERAL, |
gertk | 0:ca7defdc9e44 | 209 | FL_ON, FL_ON |
gertk | 0:ca7defdc9e44 | 210 | ); |
gertk | 0:ca7defdc9e44 | 211 | // increment framebuffer pointer |
gertk | 0:ca7defdc9e44 | 212 | pointer+=80; |
gertk | 0:ca7defdc9e44 | 213 | |
gertk | 0:ca7defdc9e44 | 214 | } else state = state_blank_area; |
gertk | 0:ca7defdc9e44 | 215 | } |
gertk | 0:ca7defdc9e44 | 216 | |
gertk | 0:ca7defdc9e44 | 217 | |
gertk | 0:ca7defdc9e44 | 218 | static void state_after_vsync(void) { |
gertk | 0:ca7defdc9e44 | 219 | if (line_counter != 38) return; |
gertk | 0:ca7defdc9e44 | 220 | state = state_visible_area; |
gertk | 0:ca7defdc9e44 | 221 | } |
gertk | 0:ca7defdc9e44 | 222 | |
gertk | 0:ca7defdc9e44 | 223 | static void state_during_vsync(void) { |
gertk | 0:ca7defdc9e44 | 224 | if (line_counter != 4) return; |
gertk | 0:ca7defdc9e44 | 225 | |
gertk | 0:ca7defdc9e44 | 226 | fl_gpio_clear_value(0, 1<<6); |
gertk | 0:ca7defdc9e44 | 227 | state = state_after_vsync; |
gertk | 0:ca7defdc9e44 | 228 | } |
gertk | 0:ca7defdc9e44 | 229 | |
gertk | 0:ca7defdc9e44 | 230 | static void state_before_vsync(void) { |
gertk | 0:ca7defdc9e44 | 231 | if (line_counter != 2) return; |
gertk | 0:ca7defdc9e44 | 232 | |
gertk | 0:ca7defdc9e44 | 233 | fl_gpio_set_value(0, 1<<6); |
gertk | 0:ca7defdc9e44 | 234 | state = state_during_vsync; |
gertk | 0:ca7defdc9e44 | 235 | } |
gertk | 0:ca7defdc9e44 | 236 | |
gertk | 0:ca7defdc9e44 | 237 | // inactive |
gertk | 0:ca7defdc9e44 | 238 | extern "C" void DMA_IRQHandler(void) __irq { |
gertk | 0:ca7defdc9e44 | 239 | fl_dma_clear_terminal_count_interrupt_request(0); |
gertk | 0:ca7defdc9e44 | 240 | |
gertk | 0:ca7defdc9e44 | 241 | } |
gertk | 0:ca7defdc9e44 | 242 | |
gertk | 0:ca7defdc9e44 | 243 | // active |
gertk | 0:ca7defdc9e44 | 244 | extern "C" void PWM1_IRQHandler(void) __irq { |
gertk | 0:ca7defdc9e44 | 245 | int regval=*FL_PWM1IR; |
gertk | 0:ca7defdc9e44 | 246 | // clear interrupt flag |
gertk | 0:ca7defdc9e44 | 247 | state(); |
gertk | 0:ca7defdc9e44 | 248 | line_counter++; |
gertk | 0:ca7defdc9e44 | 249 | *FL_PWM1IR=regval; |
gertk | 0:ca7defdc9e44 | 250 | } |
gertk | 0:ca7defdc9e44 | 251 | |
gertk | 0:ca7defdc9e44 | 252 | |
gertk | 0:ca7defdc9e44 | 253 | // ----------------------------------------------------------------------------------- |
gertk | 0:ca7defdc9e44 | 254 | |
gertk | 0:ca7defdc9e44 | 255 | void init_vga(void) { |
gertk | 0:ca7defdc9e44 | 256 | fl_power_off_all_peripherals(); |
gertk | 0:ca7defdc9e44 | 257 | |
gertk | 0:ca7defdc9e44 | 258 | init_pll0(FL_PLL0_CLOCK_SOURCE_MAIN, 2, 25, 3); // 100MHz |
gertk | 0:ca7defdc9e44 | 259 | init_uart0(0, 0, 651); // 100MHz/651/16=9600.6 (default 8N1) |
gertk | 0:ca7defdc9e44 | 260 | |
gertk | 0:ca7defdc9e44 | 261 | init_vsync(0, 6); // VSYNC on P0.6 (DIP8) |
gertk | 0:ca7defdc9e44 | 262 | init_i2s(); |
gertk | 0:ca7defdc9e44 | 263 | init_hsync(); |
gertk | 0:ca7defdc9e44 | 264 | init_dma_controller(); |
gertk | 0:ca7defdc9e44 | 265 | |
gertk | 0:ca7defdc9e44 | 266 | fl_pwm_timer_counter_enable(FL_ENABLE); |
gertk | 0:ca7defdc9e44 | 267 | fl_pwm_enable(FL_ENABLE); |
gertk | 0:ca7defdc9e44 | 268 | fl_i2s_config_dma1(FL_OFF, FL_ON, 0, 2); |
gertk | 0:ca7defdc9e44 | 269 | fl_nvic_interrupt_set_enable(FL_NVIC_INT_PWM); // start the PWM interrupts |
gertk | 0:ca7defdc9e44 | 270 | } |