pico_dsp.cpp
1 /* 2 This file is part of DISPLAY library. 3 Supports VGA and TFT display 4 5 DISPLAY library is free software: you can redistribute it and/or modify 6 it under the terms of the GNU General Public License as published by 7 the Free Software Foundation, either version 3 of the License, or 8 (at your option) any later version. 9 10 Copyright (C) 2020 J-M Harvengt 11 */ 12 13 #include "pico/stdlib.h" 14 #include "pico/multicore.h" 15 #include "hardware/spi.h" 16 #include "hardware/dma.h" 17 #include "hardware/irq.h" 18 #include <string.h> 19 20 #include "PICO_DSP.h" 21 #include "font8x8.h" 22 #include "include.h" 23 24 static gfx_mode_t gfxmode = MODE_UNDEFINED; 25 26 /* TFT structures / constants */ 27 #define digitalWrite(pin, val) gpio_put(pin, val) 28 29 #define SPICLOCK 60000000 30 #ifdef USE_VGA 31 #define SPI_MODE SPI_CPOL_1 32 #else 33 #ifdef ST7789 34 #ifdef ST7789_POL 35 #define SPI_MODE SPI_CPOL_0 36 #else 37 #define SPI_MODE SPI_CPOL_1 38 #endif 39 #endif 40 #ifdef ILI9341 41 #define SPI_MODE SPI_CPOL_0 42 #endif 43 #endif 44 45 #define LINES_PER_BLOCK 64 46 #define NR_OF_BLOCK 4 47 48 #define TFT_SWRESET 0x01 49 #define TFT_SLPOUT 0x11 50 #define TFT_INVON 0x21 51 #define TFT_DISPOFF 0x28 52 #define TFT_DISPON 0x29 53 #define TFT_CASET 0x2A 54 #define TFT_PASET 0x2B 55 #define TFT_RAMWR 0x2C 56 #define TFT_MADCTL 0x36 57 #define TFT_PIXFMT 0x3A 58 #define TFT_MADCTL_MY 0x80 59 #define TFT_MADCTL_MX 0x40 60 #define TFT_MADCTL_MV 0x20 61 #define TFT_MADCTL_ML 0x10 62 #define TFT_MADCTL_RGB 0x00 63 #define TFT_MADCTL_BGR 0x08 64 #define TFT_MADCTL_MH 0x04 65 66 static void SPItransfer(uint8_t val) 67 { 68 uint8_t dat8=val; 69 spi_write_blocking(TFT_SPIREG, &dat8, 1); 70 } 71 72 static void SPItransfer16(uint16_t val) 73 { 74 uint8_t dat8[2]; 75 dat8[0] = val>>8; 76 dat8[1] = val&0xff; 77 spi_write_blocking(TFT_SPIREG, dat8, 2); 78 } 79 80 #define DELAY_MASK 0x80 81 static const uint8_t init_commands[] = { 82 1+DELAY_MASK, TFT_SWRESET, 150, 83 1+DELAY_MASK, TFT_SLPOUT, 255, 84 2+DELAY_MASK, TFT_PIXFMT, 0x55, 10, 85 2, TFT_MADCTL, TFT_MADCTL_MV | TFT_MADCTL_BGR, 86 1, TFT_INVON, 87 1, TFT_DISPON, 88 0 89 }; 90 91 /* TFT structures / constants */ 92 #define RGBVAL16(r,g,b) ( (((r>>3)&0x1f)<<11) | (((g>>2)&0x3f)<<5) | (((b>>3)&0x1f)<<0) ) 93 94 static uint16_t * blocks[NR_OF_BLOCK]; 95 static uint16_t blocklens[NR_OF_BLOCK]; 96 static dma_channel_config dmaconfig; 97 static uint dma_tx=0; 98 static volatile uint8_t rstop = 0; 99 static volatile bool cancelled = false; 100 static volatile uint8_t curTransfer = 0; 101 static uint8_t nbTransfer = 0; 102 103 /* VGA structures / constants */ 104 #define R16(rgb) ((rgb>>8)&0xf8) 105 #define G16(rgb) ((rgb>>3)&0xfc) 106 #define B16(rgb) ((rgb<<3)&0xf8) 107 #ifdef VGA222 108 #define VGA_RGB(r,g,b) ( (((r>>6)&0x03)<<4) | (((g>>6)&0x03)<<2) | (((b>>6)&0x3)<<0) ) 109 #else 110 #define VGA_RGB(r,g,b) ( (((r>>5)&0x07)<<5) | (((g>>5)&0x07)<<2) | (((b>>6)&0x3)<<0) ) 111 #endif 112 113 // 8 bits 320x240 frame buffer => 64K 114 static vga_pixel * visible_framebuffer = NULL; 115 static vga_pixel * framebuffer = NULL; 116 static vga_pixel * fb0 = NULL; 117 static vga_pixel * fb1 = NULL; 118 119 static int fb_width; 120 static int fb_height; 121 static int fb_stride; 122 123 static const sVmode* vmode=NULL; 124 static const sVmode* volatile VgaVmodeReq = NULL; // request to reinitialize videomode, 1=only stop driver 125 126 static semaphore_t core1_initted; 127 static void core1_func(); 128 static void core1_sio_irq(); 129 static void VgaInitReql(const sVmode* vmode) 130 { 131 if (vmode == NULL) vmode = (const sVmode*)1; 132 __dmb(); 133 VgaVmodeReq = vmode; 134 while (VgaVmodeReq != NULL) { __dmb(); } 135 } 136 137 static void core1_func() 138 { 139 const sVmode* v; 140 141 multicore_fifo_clear_irq(); 142 irq_set_exclusive_handler(SIO_IRQ_PROC1,core1_sio_irq); 143 //irq_set_priority (SIO_IRQ_PROC1, 129); 144 irq_set_enabled(SIO_IRQ_PROC1,true); 145 146 sem_release(&core1_initted); 147 148 while (true) 149 { 150 __dmb(); 151 152 // initialize videomode 153 v = VgaVmodeReq; 154 if (v != NULL) 155 { 156 if ((u32)v == (u32)1) { 157 //VgaTerm(); // terminate 158 } 159 else 160 VgaInit(v,(u8*)framebuffer,320,240,320); 161 __dmb(); 162 VgaVmodeReq = NULL; 163 } 164 } 165 } 166 167 168 void PICO_DSP::setArea(uint16_t x1,uint16_t y1,uint16_t x2,uint16_t y2) { 169 int dx=0; 170 int dy=0; 171 #ifdef ST7789 172 if (TFT_REALWIDTH == TFT_REALHEIGHT) 173 { 174 #ifdef ROTATE_SCREEN 175 if (!flipped) { 176 dy += 80; 177 } 178 #else 179 if (flipped) { 180 dx += 80; 181 } 182 #endif 183 } 184 #endif 185 186 digitalWrite(_dc, 0); 187 SPItransfer(TFT_CASET); 188 digitalWrite(_dc, 1); 189 SPItransfer16(x1+dx); 190 digitalWrite(_dc, 1); 191 SPItransfer16(x2+dx); 192 digitalWrite(_dc, 0); 193 SPItransfer(TFT_PASET); 194 digitalWrite(_dc, 1); 195 SPItransfer16(y1+dy); 196 digitalWrite(_dc, 1); 197 SPItransfer16(y2+dy); 198 199 digitalWrite(_dc, 0); 200 SPItransfer(TFT_RAMWR); 201 digitalWrite(_dc, 1); 202 203 return; 204 } 205 206 207 PICO_DSP::PICO_DSP() 208 { 209 } 210 211 gfx_error_t PICO_DSP::begin(gfx_mode_t mode) 212 { 213 switch(mode) { 214 case MODE_VGA_320x240: 215 // Reset SPI if we come from TFT mode 216 if (gfxmode == MODE_TFT_320x240) { 217 fillScreenNoDma(RGBVAL16(0x0,0x00,0x00)); 218 digitalWrite(_cs, 0); 219 digitalWrite(_dc, 0); 220 SPItransfer(TFT_DISPOFF); 221 digitalWrite(_cs, 1); 222 sleep_ms(20); 223 digitalWrite(_cs, 0); 224 digitalWrite(_cs, 1); 225 if (_bkl != 0xff) { 226 digitalWrite(_bkl, 0); 227 } 228 //spi_init(TFT_SPIREG, 0); 229 //spi_deinit(TFT_SPIREG); 230 //spi_set_slave(TFT_SPIREG, true); 231 } 232 gfxmode = mode; 233 fb_width = 320; 234 fb_height = 240; 235 fb_stride = fb_width; 236 /* initialize gfx buffer */ 237 if (fb0 == NULL) { 238 void *mallocpt = malloc(fb_stride*fb_height*sizeof(vga_pixel)+4); 239 fb0 = (vga_pixel *)((void*)((intptr_t)mallocpt & ~3)); 240 } 241 visible_framebuffer = fb0; 242 framebuffer = fb0; 243 for (uint i = 0; i < fb_height*fb_width; i++) { 244 framebuffer[i] = VGA_RGB(rand() % 255,rand() % 255,rand() % 255); 245 } 246 // create a semaphore to be posted when audio init is complete 247 sem_init(&core1_initted, 0, 1); 248 multicore_launch_core1(core1_func); 249 vmode = Video(DEV_VGA, RES_QVGA); 250 VgaInitReql(vmode); 251 // wait for initialization of audio to be complete 252 sem_acquire_blocking(&core1_initted); 253 break; 254 255 case MODE_TFT_320x240: 256 gfxmode = mode; 257 fb_width = TFT_WIDTH; 258 fb_height = TFT_HEIGHT; 259 fb_stride = fb_width; 260 _cs = TFT_CS; 261 _dc = TFT_DC; 262 _rst = TFT_RST; 263 _mosi = TFT_MOSI; 264 _sclk = TFT_SCLK; 265 _bkl = TFT_BACKLIGHT; 266 gpio_init(_dc); 267 gpio_set_dir(_dc, GPIO_OUT); 268 gpio_init(_cs); 269 gpio_set_dir(_cs, GPIO_OUT); 270 digitalWrite(_cs, 1); 271 digitalWrite(_dc, 1); 272 if (_bkl != 0xff) { 273 gpio_init(_bkl); 274 gpio_set_dir(_bkl, GPIO_OUT); 275 digitalWrite(_bkl, 1); 276 } 277 278 spi_init(TFT_SPIREG, SPICLOCK); 279 spi_set_format(TFT_SPIREG, 8, SPI_MODE, SPI_CPHA_0, SPI_MSB_FIRST); 280 gpio_set_function(_sclk , GPIO_FUNC_SPI); 281 gpio_set_function(_mosi , GPIO_FUNC_SPI); 282 283 // Initialize display 284 if (_rst != 0xff) { 285 gpio_init(_rst); 286 gpio_set_dir(_rst, GPIO_OUT); 287 digitalWrite(_rst, 1); 288 sleep_ms(100); 289 digitalWrite(_rst, 0); 290 sleep_ms(100); 291 digitalWrite(_rst, 1); 292 sleep_ms(200); 293 } 294 const uint8_t *addr = init_commands; 295 uint8_t count; 296 digitalWrite(_cs, 0); 297 while (count = *addr++) { 298 uint8_t command = *addr++; 299 #ifdef ILI9341 300 if ( command == TFT_INVON ) { 301 // Skip TFT_INVON for ILI 302 } 303 else 304 #endif 305 { 306 digitalWrite(_dc, 0); // command 307 SPItransfer(command); 308 uint16_t ms = count & DELAY_MASK; 309 count &= ~DELAY_MASK; 310 while (--count > 0) { // data 311 uint8_t data = *addr++; 312 #ifdef ILI9341 313 #else 314 if ( command == TFT_MADCTL ) { 315 data = TFT_MADCTL_MX | TFT_MADCTL_MV |TFT_MADCTL_RGB; 316 } 317 #endif 318 digitalWrite(_dc, 1); 319 SPItransfer(data); 320 } 321 if (ms) { 322 ms = *addr++; // Read post-command delay time (ms) 323 if(ms == 255) ms = 500; // If 255, delay for 500 ms 324 digitalWrite(_cs, 1); 325 //SPI.endTransaction(); 326 sleep_ms(ms); 327 //SPI.beginTransaction(SPISettings(SPICLOCK, MSBFIRST, SPI_MODE)); 328 digitalWrite(_cs, 0); 329 } 330 } 331 } 332 digitalWrite(_cs, 1); 333 break; 334 } 335 336 337 return(GFX_OK); 338 } 339 340 void PICO_DSP::end() 341 { 342 } 343 344 gfx_mode_t PICO_DSP::getMode(void) 345 { 346 return gfxmode; 347 } 348 349 void PICO_DSP::flipscreen(bool flip) 350 { 351 digitalWrite(_dc, 0); 352 digitalWrite(_cs, 0); 353 SPItransfer(TFT_MADCTL); 354 digitalWrite(_dc, 1); 355 if (flip) { 356 flipped=true; 357 358 #ifdef ILI9341 359 SPItransfer(TFT_MADCTL_MV | TFT_MADCTL_BGR); 360 #endif 361 #ifdef ST7789 362 #ifdef ROTATE_SCREEN 363 SPItransfer(TFT_MADCTL_RGB); 364 #else 365 SPItransfer(TFT_MADCTL_MY | TFT_MADCTL_MV |TFT_MADCTL_RGB); 366 #endif 367 #endif 368 } 369 else { 370 flipped=false; 371 372 #ifdef ILI9341 373 SPItransfer(TFT_MADCTL_MX | TFT_MADCTL_MY | TFT_MADCTL_MV | TFT_MADCTL_BGR); 374 #endif 375 #ifdef ST7789 376 #ifdef ROTATE_SCREEN 377 SPItransfer(TFT_MADCTL_MX | TFT_MADCTL_MY | TFT_MADCTL_RGB); 378 #else 379 SPItransfer(TFT_MADCTL_MX | TFT_MADCTL_MV | TFT_MADCTL_RGB); 380 #endif 381 #endif 382 } 383 digitalWrite(_cs, 1); 384 } 385 386 387 bool PICO_DSP::isflipped(void) 388 { 389 return(flipped); 390 } 391 392 393 /*********************************************************************************************** 394 DMA functions 395 ***********************************************************************************************/ 396 static void dma_isr() { 397 irq_clear(DMA_IRQ_0); 398 dma_hw->ints0 = 1u << dma_tx; 399 curTransfer++; 400 if (curTransfer >= nbTransfer) { 401 curTransfer = 0; 402 } 403 if (cancelled) { 404 rstop = 1; 405 } 406 else 407 { 408 dma_channel_transfer_from_buffer_now(dma_tx, blocks[curTransfer], blocklens[curTransfer]); 409 } 410 } 411 412 static void setDmaStruct() { 413 // Setup the control channel 414 if (dma_tx == 0) { 415 dma_tx = dma_claim_unused_channel(true); 416 } 417 dmaconfig = dma_channel_get_default_config(dma_tx); 418 channel_config_set_transfer_data_size(&dmaconfig, DMA_SIZE_16); 419 channel_config_set_dreq(&dmaconfig, TFT_SPIDREQ); 420 //channel_config_set_read_increment(&dmaconfig, true); // read incrementing 421 //channel_config_set_write_increment(&dmaconfig, false); // no write incrementing 422 423 dma_channel_configure( 424 dma_tx, 425 &dmaconfig, 426 &spi_get_hw(TFT_SPIREG)->dr, // write address 427 blocks[0], 428 blocklens[0], 429 false 430 ); 431 432 irq_set_exclusive_handler(DMA_IRQ_0, dma_isr); 433 dma_channel_set_irq0_enabled(dma_tx, true); 434 irq_set_enabled(DMA_IRQ_0, true); 435 dma_hw->ints0 = 1u << dma_tx; 436 } 437 438 void PICO_DSP::startRefresh(void) { 439 if (gfxmode == MODE_TFT_320x240) { 440 uint32_t remaining = TFT_HEIGHT*TFT_WIDTH*2; 441 int i=0; 442 nbTransfer = 0; 443 while (remaining > 0) { 444 uint16_t * fb = blocks[i]; 445 int32_t len = (remaining >= (LINES_PER_BLOCK*TFT_WIDTH*2)?LINES_PER_BLOCK*TFT_WIDTH*2:remaining); 446 switch (i) { 447 case 0: 448 if (fb == 0) fb = (uint16_t*)((int)malloc(len+64)&0xffffffe0); 449 break; 450 case 1: 451 if (fb == 0) fb = (uint16_t*)((int)malloc(len+64)&0xffffffe0); 452 break; 453 case 2: 454 if (fb == 0) fb = (uint16_t*)((int)malloc(len+64)&0xffffffe0); 455 break; 456 case 3: 457 if (fb == 0) fb = (uint16_t*)((int)malloc(len+64)&0xffffffe0); 458 break; 459 } 460 blocks[i] = fb; 461 blocklens[i] = len/2; 462 if (blocks[i] == 0) { 463 fillScreenNoDma(RGBVAL16(0xFF,0xFF,0x00)); 464 printf("FB allocaltion failed for block %d\n",i); 465 sleep_ms(10000); 466 } 467 nbTransfer++; 468 remaining -= len; 469 i++; 470 } 471 curTransfer = 0; 472 rstop = 0; 473 digitalWrite(_cs, 1); 474 setDmaStruct(); 475 fillScreen(RGBVAL16(0x00,0x00,0x00)); 476 digitalWrite(_cs, 0); 477 478 setArea((TFT_REALWIDTH-TFT_WIDTH)/2, (TFT_REALHEIGHT-TFT_HEIGHT)/2, (TFT_REALWIDTH-TFT_WIDTH)/2 + TFT_WIDTH-1, (TFT_REALHEIGHT-TFT_HEIGHT)/2+TFT_HEIGHT-1); 479 // we switch to 16bit mode!! 480 spi_set_format(TFT_SPIREG, 16, SPI_CPOL_0, SPI_CPHA_0, SPI_MSB_FIRST); 481 dma_start_channel_mask(1u << dma_tx); 482 } 483 else { 484 fillScreen(RGBVAL16(0x00,0x00,0x00)); 485 } 486 } 487 488 void PICO_DSP::stopRefresh(void) { 489 if (gfxmode == MODE_TFT_320x240) { 490 rstop = 1; 491 unsigned long m = time_us_32()*1000; 492 cancelled = true; 493 while (!rstop) { 494 if ((time_us_32()*1000 - m) > 100) break; 495 sleep_ms(100); 496 asm volatile("wfi"); 497 }; 498 rstop = 0; 499 sleep_ms(100); 500 cancelled = false; 501 //dmatx.detachInterrupt(); 502 fillScreen(RGBVAL16(0x00,0x00,0x00)); 503 digitalWrite(_cs, 1); 504 // we switch back to GFX mode!! 505 begin(gfxmode); 506 setArea(0, 0, TFT_REALWIDTH-1, TFT_REALHEIGHT-1); 507 } 508 } 509 510 511 /*********************************************************************************************** 512 GFX functions 513 ***********************************************************************************************/ 514 // retrieve size of the frame buffer 515 int PICO_DSP::get_frame_buffer_size(int *width, int *height) 516 { 517 if (width != nullptr) *width = fb_width; 518 if (height != nullptr) *height = fb_height; 519 return fb_stride; 520 } 521 522 void PICO_DSP::waitSync() 523 { 524 if (gfxmode == MODE_TFT_320x240) { 525 } 526 else { 527 WaitVSync(); 528 } 529 } 530 531 void PICO_DSP::waitLine(int line) 532 { 533 if (gfxmode == MODE_TFT_320x240) { 534 } 535 else { 536 // while (currentLine != line) {}; 537 } 538 } 539 540 541 /*********************************************************************************************** 542 GFX functions 543 ***********************************************************************************************/ 544 /* 545 vga_pixel * PICO_DSP::getLineBuffer(int j) { 546 return (&framebuffer[j*fb_stride]); 547 } 548 */ 549 550 void PICO_DSP::fillScreen(dsp_pixel color) { 551 int i,j; 552 if (gfxmode == MODE_TFT_320x240) { 553 for (j=0; j<TFT_HEIGHT; j++) 554 { 555 uint16_t * block=blocks[j>>6]; 556 uint16_t * dst=&block[(j&0x3F)*fb_stride]; 557 for (i=0; i<fb_width; i++) 558 { 559 *dst++ = color; 560 } 561 } 562 } 563 else { 564 vga_pixel color8 = VGA_RGB(R16(color),G16(color),B16(color)); 565 for (j=0; j<fb_height; j++) 566 { 567 vga_pixel * dst=&framebuffer[j*fb_stride]; 568 for (i=0; i<fb_width; i++) 569 { 570 *dst++ = color8; 571 } 572 } 573 } 574 } 575 576 void PICO_DSP::drawRect(int16_t x, int16_t y, int16_t w, int16_t h, dsp_pixel color) { 577 int i,j,l=y; 578 if (gfxmode == MODE_TFT_320x240) { 579 for (j=0; j<h; j++) 580 { 581 uint16_t * block=blocks[l>>6]; 582 uint16_t * dst=&block[(l&0x3F)*fb_stride+x]; 583 for (i=0; i<w; i++) 584 { 585 *dst++ = color; 586 } 587 l++; 588 } 589 } 590 else { 591 vga_pixel color8 = VGA_RGB(R16(color),G16(color),B16(color)); 592 for (j=0; j<h; j++) 593 { 594 vga_pixel * dst=&framebuffer[l*fb_stride+x]; 595 for (i=0; i<w; i++) 596 { 597 *dst++ = color8; 598 } 599 l++; 600 } 601 } 602 } 603 604 void PICO_DSP::drawText(int16_t x, int16_t y, const char * text, dsp_pixel fgcolor, dsp_pixel bgcolor, bool doublesize) { 605 if (gfxmode == MODE_TFT_320x240) { 606 uint16_t c; 607 uint16_t * block; 608 uint16_t * dst; 609 fgcolor = fgcolor; 610 bgcolor = bgcolor; 611 while ((c = *text++)) { 612 const unsigned char * charpt=&font8x8[c][0]; 613 int l=y; 614 for (int i=0;i<8;i++) 615 { 616 unsigned char bits; 617 if (doublesize) { 618 block=blocks[l>>6]; 619 dst=&block[(l&0x3F)*fb_stride+x]; 620 bits = *charpt; 621 if (bits&0x01) *dst++=fgcolor; 622 else *dst++=bgcolor; 623 bits = bits >> 1; 624 if (bits&0x01) *dst++=fgcolor; 625 else *dst++=bgcolor; 626 bits = bits >> 1; 627 if (bits&0x01) *dst++=fgcolor; 628 else *dst++=bgcolor; 629 bits = bits >> 1; 630 if (bits&0x01) *dst++=fgcolor; 631 else *dst++=bgcolor; 632 bits = bits >> 1; 633 if (bits&0x01) *dst++=fgcolor; 634 else *dst++=bgcolor; 635 bits = bits >> 1; 636 if (bits&0x01) *dst++=fgcolor; 637 else *dst++=bgcolor; 638 bits = bits >> 1; 639 if (bits&0x01) *dst++=fgcolor; 640 else *dst++=bgcolor; 641 bits = bits >> 1; 642 if (bits&0x01) *dst++=fgcolor; 643 else *dst++=bgcolor; 644 l++; 645 } 646 block=blocks[l>>6]; 647 dst=&block[(l&0x3F)*fb_stride+x]; 648 bits = *charpt++; 649 if (bits&0x01) *dst++=fgcolor; 650 else *dst++=bgcolor; 651 bits = bits >> 1; 652 if (bits&0x01) *dst++=fgcolor; 653 else *dst++=bgcolor; 654 bits = bits >> 1; 655 if (bits&0x01) *dst++=fgcolor; 656 else *dst++=bgcolor; 657 bits = bits >> 1; 658 if (bits&0x01) *dst++=fgcolor; 659 else *dst++=bgcolor; 660 bits = bits >> 1; 661 if (bits&0x01) *dst++=fgcolor; 662 else *dst++=bgcolor; 663 bits = bits >> 1; 664 if (bits&0x01) *dst++=fgcolor; 665 else *dst++=bgcolor; 666 bits = bits >> 1; 667 if (bits&0x01) *dst++=fgcolor; 668 else *dst++=bgcolor; 669 bits = bits >> 1; 670 if (bits&0x01) *dst++=fgcolor; 671 else *dst++=bgcolor; 672 l++; 673 } 674 x +=8; 675 } 676 } 677 else { 678 vga_pixel fgcolor8 = VGA_RGB(R16(fgcolor),G16(fgcolor),B16(fgcolor)); 679 vga_pixel bgcolor8 = VGA_RGB(R16(bgcolor),G16(bgcolor),B16(bgcolor)); 680 vga_pixel c; 681 vga_pixel * dst; 682 while ((c = *text++)) { 683 const unsigned char * charpt=&font8x8[c][0]; 684 int l=y; 685 for (int i=0;i<8;i++) 686 { 687 unsigned char bits; 688 if (doublesize) { 689 dst=&framebuffer[l*fb_stride+x]; 690 bits = *charpt; 691 if (bits&0x01) *dst++=fgcolor8; 692 else *dst++=bgcolor8; 693 bits = bits >> 1; 694 if (bits&0x01) *dst++=fgcolor8; 695 else *dst++=bgcolor8; 696 bits = bits >> 1; 697 if (bits&0x01) *dst++=fgcolor8; 698 else *dst++=bgcolor8; 699 bits = bits >> 1; 700 if (bits&0x01) *dst++=fgcolor8; 701 else *dst++=bgcolor8; 702 bits = bits >> 1; 703 if (bits&0x01) *dst++=fgcolor8; 704 else *dst++=bgcolor8; 705 bits = bits >> 1; 706 if (bits&0x01) *dst++=fgcolor8; 707 else *dst++=bgcolor8; 708 bits = bits >> 1; 709 if (bits&0x01) *dst++=fgcolor8; 710 else *dst++=bgcolor8; 711 bits = bits >> 1; 712 if (bits&0x01) *dst++=fgcolor8; 713 else *dst++=bgcolor8; 714 l++; 715 } 716 dst=&framebuffer[l*fb_stride+x]; 717 bits = *charpt++; 718 if (bits&0x01) *dst++=fgcolor8; 719 else *dst++=bgcolor8; 720 bits = bits >> 1; 721 if (bits&0x01) *dst++=fgcolor8; 722 else *dst++=bgcolor8; 723 bits = bits >> 1; 724 if (bits&0x01) *dst++=fgcolor8; 725 else *dst++=bgcolor8; 726 bits = bits >> 1; 727 if (bits&0x01) *dst++=fgcolor8; 728 else *dst++=bgcolor8; 729 bits = bits >> 1; 730 if (bits&0x01) *dst++=fgcolor8; 731 else *dst++=bgcolor8; 732 bits = bits >> 1; 733 if (bits&0x01) *dst++=fgcolor8; 734 else *dst++=bgcolor8; 735 bits = bits >> 1; 736 if (bits&0x01) *dst++=fgcolor8; 737 else *dst++=bgcolor8; 738 bits = bits >> 1; 739 if (bits&0x01) *dst++=fgcolor8; 740 else *dst++=bgcolor8; 741 l++; 742 } 743 x +=8; 744 } 745 } 746 } 747 748 void PICO_DSP::drawSprite(int16_t x, int16_t y, const dsp_pixel *bitmap, uint16_t arx, uint16_t ary, uint16_t arw, uint16_t arh) 749 { 750 int bmp_offx = 0; 751 int bmp_offy = 0; 752 uint16_t *bmp_ptr; 753 int w =*bitmap++; 754 int h = *bitmap++; 755 if ( (arw == 0) || (arh == 0) ) { 756 // no crop window 757 arx = x; 758 ary = y; 759 arw = w; 760 arh = h; 761 } 762 else { 763 if ( (x>(arx+arw)) || ((x+w)<arx) || (y>(ary+arh)) || ((y+h)<ary) ) { 764 return; 765 } 766 // crop area 767 if ( (x > arx) && (x<(arx+arw)) ) { 768 arw = arw - (x-arx); 769 arx = arx + (x-arx); 770 } else { 771 bmp_offx = arx; 772 } 773 if ( ((x+w) > arx) && ((x+w)<(arx+arw)) ) { 774 arw -= (arx+arw-x-w); 775 } 776 if ( (y > ary) && (y<(ary+arh)) ) { 777 arh = arh - (y-ary); 778 ary = ary + (y-ary); 779 } else { 780 bmp_offy = ary; 781 } 782 if ( ((y+h) > ary) && ((y+h)<(ary+arh)) ) { 783 arh -= (ary+arh-y-h); 784 } 785 } 786 int l=ary; 787 bitmap = bitmap + bmp_offy*w + bmp_offx; 788 789 790 if (gfxmode == MODE_TFT_320x240) { 791 for (int row=0;row<arh; row++) 792 { 793 uint16_t * block=blocks[l>>6]; 794 uint16_t * dst=&block[(l&0x3F)*fb_stride+arx]; 795 bmp_ptr = (uint16_t*)bitmap; 796 for (int col=0;col<arw; col++) 797 { 798 *dst++ = *bmp_ptr++; 799 } 800 bitmap += w; 801 l++; 802 } 803 } 804 else { 805 for (int row=0;row<arh; row++) 806 { 807 vga_pixel * dst=&framebuffer[l*fb_stride+arx]; 808 bmp_ptr = (uint16_t *)bitmap; 809 for (int col=0;col<arw; col++) 810 { 811 uint16_t pix= *bmp_ptr++; 812 *dst++ = VGA_RGB(R16(pix),G16(pix),B16(pix)); 813 } 814 bitmap += w; 815 l++; 816 } 817 } 818 819 } 820 821 void PICO_DSP::drawSprite(int16_t x, int16_t y, const dsp_pixel *bitmap) { 822 drawSprite(x,y,bitmap, 0,0,0,0); 823 } 824 825 void PICO_DSP::writeLine(int width, int height, int y, dsp_pixel *buf) { 826 if (gfxmode == MODE_TFT_320x240) { 827 uint16_t * block=blocks[y>>6]; 828 uint16_t * dst=&block[(y&0x3F)*fb_stride]; 829 if (width > fb_width) { 830 #ifdef TFT_LINEARINT 831 int delta = (width/(width-fb_width))-1; 832 int pos = delta; 833 for (int i=0; i<fb_width; i++) 834 { 835 uint16_t val = *buf++; 836 pos--; 837 if (pos == 0) { 838 #ifdef LINEARINT_HACK 839 val = ((uint32_t)*buf++ + val)/2; 840 #else 841 uint16_t val2 = *buf++; 842 val = RGBVAL16((R16(val)+R16(val2))/2,(G16(val)+G16(val2))/2,(B16(val)+B16(val2))/2); 843 #endif 844 pos = delta; 845 } 846 *dst++=val; 847 } 848 #else 849 int step = ((width << 8)/fb_width); 850 int pos = 0; 851 for (int i=0; i<fb_width; i++) 852 { 853 *dst++=buf[pos >> 8]; 854 pos +=step; 855 } 856 #endif 857 } 858 else if ((width*2) == fb_width) 859 { 860 for (int i=0; i<width; i++) 861 { 862 *dst++=*buf; 863 *dst++=*buf++; 864 } 865 } 866 else 867 { 868 if (width <= fb_width) { 869 dst += (fb_width-width)/2; 870 } 871 for (int i=0; i<width; i++) 872 { 873 *dst++=*buf++; 874 } 875 } 876 } 877 else { 878 if ( (height<fb_height) && (height > 2) ) y += (fb_height-height)/2; 879 vga_pixel * dst=&framebuffer[y*fb_stride]; 880 if (width > fb_width) { 881 int step = ((width << 8)/fb_width); 882 int pos = 0; 883 for (int i=0; i<fb_width; i++) 884 { 885 uint16_t pix = buf[pos >> 8]; 886 *dst++ = VGA_RGB(R16(pix),G16(pix),B16(pix)); 887 pos +=step; 888 } 889 } 890 else if ((width*2) == fb_width) { 891 for (int i=0; i<width; i++) 892 { 893 uint16_t pix = *buf++; 894 vga_pixel col = VGA_RGB(R16(pix),G16(pix),B16(pix)); 895 *dst++= col; 896 *dst++= col; 897 } 898 } 899 else { 900 if (width <= fb_width) { 901 dst += (fb_width-width)/2; 902 } 903 for (int i=0; i<width; i++) 904 { 905 uint16_t pix = *buf++; 906 *dst++= VGA_RGB(R16(pix),G16(pix),B16(pix)); 907 } 908 } 909 } 910 } 911 912 void PICO_DSP::writeLinePal(int width, int height, int y, uint8_t *buf, dsp_pixel *palette) { 913 if (gfxmode == MODE_TFT_320x240) { 914 if ( (height<fb_height) && (height > 2) ) y += (fb_height-height)/2; 915 uint16_t * block=blocks[y>>6]; 916 uint16_t * dst=&block[(y&0x3F)*fb_stride]; 917 if (width > fb_width) { 918 #ifdef TFT_LINEARINT 919 int delta = (width/(width-fb_width))-1; 920 int pos = delta; 921 for (int i=0; i<fb_width; i++) 922 { 923 uint16_t val = palette[*buf++]; 924 pos--; 925 if (pos == 0) { 926 #ifdef LINEARINT_HACK 927 val = ((uint32_t)palette[*buf++] + val)/2; 928 #else 929 uint16_t val2 = *buf++; 930 val = RGBVAL16((R16(val)+R16(val2))/2,(G16(val)+G16(val2))/2,(B16(val)+B16(val2))/2); 931 #endif 932 pos = delta; 933 } 934 *dst++=val; 935 } 936 #else 937 int step = ((width << 8)/fb_width); 938 int pos = 0; 939 for (int i=0; i<fb_width; i++) 940 { 941 *dst++=palette[buf[pos >> 8]]; 942 pos +=step; 943 } 944 #endif 945 } 946 else if ((width*2) == fb_width) { 947 for (int i=0; i<width; i++) 948 { 949 *dst++=palette[*buf]; 950 *dst++=palette[*buf++]; 951 } 952 } 953 else { 954 if (width <= fb_width) { 955 dst += (fb_width-width)/2; 956 } 957 for (int i=0; i<width; i++) 958 { 959 *dst++=palette[*buf++]; 960 } 961 } 962 } 963 else { 964 if ( (height<fb_height) && (height > 2) ) y += (fb_height-height)/2; 965 vga_pixel * dst=&framebuffer[y*fb_stride]; 966 if (width > fb_width) { 967 int step = ((width << 8)/fb_width); 968 int pos = 0; 969 for (int i=0; i<fb_width; i++) 970 { 971 uint16_t pix = palette[buf[pos >> 8]]; 972 *dst++= VGA_RGB(R16(pix),G16(pix),B16(pix)); 973 pos +=step; 974 } 975 } 976 else if ((width*2) == fb_width) { 977 for (int i=0; i<width; i++) 978 { 979 uint16_t pix = palette[*buf++]; 980 *dst++= VGA_RGB(R16(pix),G16(pix),B16(pix)); 981 *dst++= VGA_RGB(R16(pix),G16(pix),B16(pix)); 982 } 983 } 984 else { 985 if (width <= fb_width) { 986 dst += (fb_width-width)/2; 987 } 988 for (int i=0; i<width; i++) 989 { 990 uint16_t pix = palette[*buf++]; 991 *dst++= VGA_RGB(R16(pix),G16(pix),B16(pix)); 992 } 993 } 994 } 995 } 996 997 void PICO_DSP::writeScreenPal(int width, int height, int stride, uint8_t *buf, dsp_pixel *palette16) { 998 uint8_t *src; 999 int i,j,y=0; 1000 int sy = 0; 1001 int systep=(1<<8); 1002 int h = height; 1003 if (height <= ( (2*fb_height)/3)) { 1004 systep=(systep*height)/fb_height; 1005 h = fb_height; 1006 } 1007 if (gfxmode == MODE_TFT_320x240) { 1008 if (width*2 <= fb_width) { 1009 for (j=0; j<h; j++) 1010 { 1011 uint16_t * block=blocks[y>>6]; 1012 uint16_t * dst=&block[(y&0x3F)*fb_stride]; 1013 src=&buf[(sy>>8)*stride]; 1014 for (i=0; i<width; i++) 1015 { 1016 uint16_t val = palette16[*src++]; 1017 *dst++ = val; 1018 *dst++ = val; 1019 } 1020 y++; 1021 sy+=systep; 1022 } 1023 } 1024 else if (width <= fb_width) { 1025 for (j=0; j<h; j++) 1026 { 1027 uint16_t * block=blocks[y>>6]; 1028 uint16_t * dst=&block[(y&0x3F)*fb_stride+(fb_width-width)/2]; 1029 src=&buf[(sy>>8)*stride]; 1030 for (i=0; i<width; i++) 1031 { 1032 uint16_t val = palette16[*src++]; 1033 *dst++ = val; 1034 } 1035 y++; 1036 sy+=systep; 1037 } 1038 } 1039 } 1040 else { // VGA 1041 if (width*2 <= fb_width) { 1042 for (j=0; j<h; j++) 1043 { 1044 vga_pixel * dst=&framebuffer[y*fb_stride]; 1045 src=&buf[(sy>>8)*stride]; 1046 for (i=0; i<width; i++) 1047 { 1048 uint16_t pix = palette16[*src++]; 1049 *dst++ = VGA_RGB(R16(pix),G16(pix),B16(pix)); 1050 *dst++ = VGA_RGB(R16(pix),G16(pix),B16(pix)); 1051 } 1052 y++; 1053 sy+=systep; 1054 } 1055 } 1056 else if (width <= fb_width) { 1057 for (j=0; j<h; j++) 1058 { 1059 vga_pixel * dst=&framebuffer[y*fb_stride+(fb_width-width)/2]; 1060 src=&buf[(sy>>8)*stride]; 1061 for (i=0; i<width; i++) 1062 { 1063 uint16_t pix = palette16[*src++]; 1064 *dst++ = VGA_RGB(R16(pix),G16(pix),B16(pix)); 1065 } 1066 y++; 1067 sy+=systep; 1068 } 1069 } 1070 } 1071 } 1072 1073 1074 /*********************************************************************************************** 1075 No DMA functions 1076 ***********************************************************************************************/ 1077 void PICO_DSP::fillScreenNoDma(dsp_pixel color) { 1078 if (gfxmode == MODE_TFT_320x240) { 1079 digitalWrite(_cs, 0); 1080 setArea(0, 0, TFT_REALWIDTH-1, TFT_REALHEIGHT-1); 1081 int i,j; 1082 for (j=0; j<TFT_REALHEIGHT; j++) 1083 { 1084 for (i=0; i<TFT_REALWIDTH; i++) { 1085 //digitalWrite(_dc, 1); 1086 SPItransfer16(color); 1087 } 1088 } 1089 #ifdef ILI9341 1090 digitalWrite(_dc, 0); 1091 SPItransfer(ILI9341_SLPOUT); 1092 digitalWrite(_dc, 1); 1093 #endif 1094 digitalWrite(_cs, 1); 1095 setArea(0, 0, (TFT_REALWIDTH-1), (TFT_REALHEIGHT-1)); 1096 } 1097 else { 1098 fillScreen(color); 1099 } 1100 } 1101 1102 void PICO_DSP::drawRectNoDma(int16_t x, int16_t y, int16_t w, int16_t h, dsp_pixel color) { 1103 if (gfxmode == MODE_TFT_320x240) { 1104 digitalWrite(_cs, 0); 1105 setArea(x,y,x+w-1,y+h-1); 1106 int i; 1107 for (i=0; i<(w*h); i++) 1108 { 1109 SPItransfer16(color); 1110 } 1111 #ifdef ILI9341 1112 digitalWrite(_dc, 0); 1113 SPItransfer(ILI9341_SLPOUT); 1114 digitalWrite(_dc, 1); 1115 #endif 1116 digitalWrite(_cs, 1); 1117 setArea(0, 0, (TFT_REALWIDTH-1), (TFT_REALHEIGHT-1)); 1118 } 1119 else { 1120 drawRect(x, y, w, h, color); 1121 } 1122 } 1123 1124 1125 void PICO_DSP::drawSpriteNoDma(int16_t x, int16_t y, const dsp_pixel *bitmap) { 1126 drawSpriteNoDma(x,y,bitmap, 0,0,0,0); 1127 } 1128 1129 void PICO_DSP::drawSpriteNoDma(int16_t x, int16_t y, const dsp_pixel *bitmap, uint16_t arx, uint16_t ary, uint16_t arw, uint16_t arh) 1130 { 1131 if (gfxmode == MODE_TFT_320x240) { 1132 int bmp_offx = 0; 1133 int bmp_offy = 0; 1134 uint16_t *bmp_ptr; 1135 int w =*bitmap++; 1136 int h =*bitmap++; 1137 if ( (arw == 0) || (arh == 0) ) { 1138 // no crop window 1139 arx = x; 1140 ary = y; 1141 arw = w; 1142 arh = h; 1143 } 1144 else { 1145 if ( (x>(arx+arw)) || ((x+w)<arx) || (y>(ary+arh)) || ((y+h)<ary) ) { 1146 return; 1147 } 1148 // crop area 1149 if ( (x > arx) && (x<(arx+arw)) ) { 1150 arw = arw - (x-arx); 1151 arx = arx + (x-arx); 1152 } else { 1153 bmp_offx = arx; 1154 } 1155 if ( ((x+w) > arx) && ((x+w)<(arx+arw)) ) { 1156 arw -= (arx+arw-x-w); 1157 } 1158 if ( (y > ary) && (y<(ary+arh)) ) { 1159 arh = arh - (y-ary); 1160 ary = ary + (y-ary); 1161 } else { 1162 bmp_offy = ary; 1163 } 1164 if ( ((y+h) > ary) && ((y+h)<(ary+arh)) ) { 1165 arh -= (ary+arh-y-h); 1166 } 1167 } 1168 digitalWrite(_cs, 0); 1169 setArea(arx, ary, arx+arw-1, ary+arh-1); 1170 bitmap = bitmap + bmp_offy*w + bmp_offx; 1171 for (int row=0;row<arh; row++) 1172 { 1173 bmp_ptr = (uint16_t*)bitmap; 1174 for (int col=0;col<arw; col++) 1175 { 1176 SPItransfer16(*bmp_ptr++); 1177 } 1178 bitmap += w; 1179 } 1180 #ifdef ILI9341 1181 digitalWrite(_dc, 0); 1182 SPItransfer(ILI9341_SLPOUT); 1183 digitalWrite(_dc, 1); 1184 #endif 1185 setArea(0, 0, TFT_REALWIDTH-1, TFT_REALHEIGHT-1); 1186 digitalWrite(_cs, 1); 1187 } 1188 else { 1189 drawSprite(x, y, bitmap, arx, ary, arw, arh); 1190 } 1191 } 1192 1193 void PICO_DSP::drawTextNoDma(int16_t x, int16_t y, const char * text, dsp_pixel fgcolor, dsp_pixel bgcolor, bool doublesize) { 1194 if (gfxmode == MODE_TFT_320x240) { 1195 uint16_t c; 1196 while ((c = *text++)) { 1197 const unsigned char * charpt=&font8x8[c][0]; 1198 digitalWrite(_cs, 0); 1199 setArea(x,y,x+7,y+(doublesize?15:7)); 1200 for (int i=0;i<8;i++) 1201 { 1202 unsigned char bits; 1203 if (doublesize) { 1204 bits = *charpt; 1205 if (bits&0x01) SPItransfer16(fgcolor); 1206 else SPItransfer16(bgcolor); 1207 bits = bits >> 1; 1208 if (bits&0x01) SPItransfer16(fgcolor); 1209 else SPItransfer16(bgcolor); 1210 bits = bits >> 1; 1211 if (bits&0x01) SPItransfer16(fgcolor); 1212 else SPItransfer16(bgcolor); 1213 bits = bits >> 1; 1214 if (bits&0x01) SPItransfer16(fgcolor); 1215 else SPItransfer16(bgcolor); 1216 bits = bits >> 1; 1217 if (bits&0x01) SPItransfer16(fgcolor); 1218 else SPItransfer16(bgcolor); 1219 bits = bits >> 1; 1220 if (bits&0x01) SPItransfer16(fgcolor); 1221 else SPItransfer16(bgcolor); 1222 bits = bits >> 1; 1223 if (bits&0x01) SPItransfer16(fgcolor); 1224 else SPItransfer16(bgcolor); 1225 bits = bits >> 1; 1226 if (bits&0x01) SPItransfer16(fgcolor); 1227 else SPItransfer16(bgcolor); 1228 } 1229 bits = *charpt++; 1230 if (bits&0x01) SPItransfer16(fgcolor); 1231 else SPItransfer16(bgcolor); 1232 bits = bits >> 1; 1233 if (bits&0x01) SPItransfer16(fgcolor); 1234 else SPItransfer16(bgcolor); 1235 bits = bits >> 1; 1236 if (bits&0x01) SPItransfer16(fgcolor); 1237 else SPItransfer16(bgcolor); 1238 bits = bits >> 1; 1239 if (bits&0x01) SPItransfer16(fgcolor); 1240 else SPItransfer16(bgcolor); 1241 bits = bits >> 1; 1242 if (bits&0x01) SPItransfer16(fgcolor); 1243 else SPItransfer16(bgcolor); 1244 bits = bits >> 1; 1245 if (bits&0x01) SPItransfer16(fgcolor); 1246 else SPItransfer16(bgcolor); 1247 bits = bits >> 1; 1248 if (bits&0x01) SPItransfer16(fgcolor); 1249 else SPItransfer16(bgcolor); 1250 bits = bits >> 1; 1251 if (bits&0x01) SPItransfer16(fgcolor); 1252 else SPItransfer16(bgcolor); 1253 } 1254 x +=8; 1255 #ifdef ILI9341 1256 digitalWrite(_dc, 0); 1257 SPItransfer(ILI9341_SLPOUT); 1258 digitalWrite(_dc, 1); 1259 #endif 1260 digitalWrite(_cs, 1); 1261 } 1262 1263 digitalWrite(_cs, 0); 1264 setArea(0, 0, (TFT_REALWIDTH-1), (TFT_REALHEIGHT-1)); 1265 digitalWrite(_cs, 1); 1266 } 1267 else { 1268 drawText(x, y, text, fgcolor, bgcolor, doublesize); 1269 } 1270 } 1271 1272 /******************************************************************* 1273 Experimental PWM interrupt based sound driver !!! 1274 *******************************************************************/ 1275 #include "hardware/irq.h" 1276 #include "hardware/pwm.h" 1277 1278 static bool fillfirsthalf = true; 1279 static uint16_t cnt = 0; 1280 static uint16_t sampleBufferSize = 0; 1281 1282 static void (*fillsamples)(short * stream, int len) = nullptr; 1283 1284 static uint32_t * i2s_tx_buffer; 1285 static short * i2s_tx_buffer16; 1286 1287 static void SOFTWARE_isr() { 1288 if (fillfirsthalf) { 1289 fillsamples((short *)i2s_tx_buffer, sampleBufferSize); 1290 } 1291 else { 1292 fillsamples((short *)&i2s_tx_buffer[sampleBufferSize/2], sampleBufferSize); 1293 } 1294 } 1295 1296 static void AUDIO_isr() { 1297 pwm_clear_irq(pwm_gpio_to_slice_num(AUDIO_PIN)); 1298 long s = i2s_tx_buffer16[cnt++]; 1299 s += i2s_tx_buffer16[cnt++]; 1300 s = s/2 + 32767; 1301 pwm_set_gpio_level(AUDIO_PIN, s >> 8); 1302 cnt = cnt & (sampleBufferSize*2-1); 1303 1304 if (cnt == 0) { 1305 fillfirsthalf = false; 1306 //irq_set_pending(RTC_IRQ+1); 1307 multicore_fifo_push_blocking(0); 1308 } 1309 else if (cnt == sampleBufferSize) { 1310 fillfirsthalf = true; 1311 //irq_set_pending(RTC_IRQ+1); 1312 multicore_fifo_push_blocking(0); 1313 } 1314 } 1315 1316 static void core1_sio_irq() { 1317 irq_clear(SIO_IRQ_PROC1); 1318 while(multicore_fifo_rvalid()) { 1319 uint16_t raw = multicore_fifo_pop_blocking(); 1320 SOFTWARE_isr(); 1321 } 1322 multicore_fifo_clear_irq(); 1323 } 1324 1325 static void core1_func_tft() { 1326 multicore_fifo_clear_irq(); 1327 irq_set_exclusive_handler(SIO_IRQ_PROC1,core1_sio_irq); 1328 //irq_set_priority (SIO_IRQ_PROC1, 129); 1329 irq_set_enabled(SIO_IRQ_PROC1,true); 1330 1331 while (true) { 1332 tight_loop_contents(); 1333 } 1334 } 1335 1336 void PICO_DSP::begin_audio(int samplesize, void (*callback)(short * stream, int len)) 1337 { 1338 fillsamples = callback; 1339 i2s_tx_buffer = (uint32_t*)malloc(samplesize*sizeof(uint32_t)); 1340 1341 if (i2s_tx_buffer == NULL) { 1342 printf("sound buffer could not be allocated!!!!!\n"); 1343 return; 1344 } 1345 memset((void*)i2s_tx_buffer,0, samplesize*sizeof(uint32_t)); 1346 printf("sound buffer allocated\n"); 1347 1348 i2s_tx_buffer16 = (short*)i2s_tx_buffer; 1349 1350 sampleBufferSize = samplesize; 1351 1352 gpio_set_function(AUDIO_PIN, GPIO_FUNC_PWM); 1353 1354 if (gfxmode == MODE_TFT_320x240) { 1355 multicore_launch_core1(core1_func_tft); 1356 } 1357 1358 int audio_pin_slice = pwm_gpio_to_slice_num(AUDIO_PIN); 1359 // Setup PWM interrupt to fire when PWM cycle is complete 1360 pwm_clear_irq(audio_pin_slice); 1361 pwm_set_irq_enabled(audio_pin_slice, true); 1362 irq_set_exclusive_handler(PWM_IRQ_WRAP, AUDIO_isr); 1363 irq_set_priority (PWM_IRQ_WRAP, 128); 1364 irq_set_enabled(PWM_IRQ_WRAP, true); 1365 1366 //irq_set_exclusive_handler(RTC_IRQ+1,SOFTWARE_isr); 1367 //irq_set_priority (RTC_IRQ+1, 120); 1368 //irq_set_enabled(RTC_IRQ+1,true); 1369 1370 1371 // Setup PWM for audio output 1372 pwm_config config = pwm_get_default_config(); 1373 // pwm_config_set_clkdiv(&config, 5.5f); 1374 pwm_config_set_clkdiv(&config, 50.0f); 1375 pwm_config_set_wrap(&config, 254); 1376 pwm_init(audio_pin_slice, &config, true); 1377 1378 pwm_set_gpio_level(AUDIO_PIN, 0); 1379 printf("sound initialized\n"); 1380 } 1381 1382 void PICO_DSP::end_audio() 1383 { 1384 if (i2s_tx_buffer != NULL) { 1385 free(i2s_tx_buffer); 1386 } 1387 } 1388 1389 1390 1391