#include "fb.h" #include "io.h" #include "multicore.h" #define PWM_BASE (PERIPHERAL_BASE + 0x20C000 + 0x800) /* PWM1 register base address on RPi4 */ #define PWM_LEGACY_BASE (LEGACY_BASE + 0x20C000 + 0x800) /* PWM1 register base legacy address on RPi4 */ #define CLOCK_BASE (PERIPHERAL_BASE + 0x101000) #define DMA_BASE (PERIPHERAL_BASE + 0x007100) /* DMA register base address */ #define DMA_ENABLE (DMA_BASE + 0xFF0) /* DMA global enable bits */ #define BCM2711_PWMCLK_CNTL 40 #define BCM2711_PWMCLK_DIV 41 #define PM_PASSWORD 0x5A000000 #define BCM2711_PWM_CONTROL 0 #define BCM2711_PWM_STATUS 1 #define BCM2711_PWM_DMAC 2 #define BCM2711_PWM0_RANGE 4 #define BCM2711_PWM0_DATA 5 #define BCM2711_PWM_FIFO 6 #define BCM2711_PWM1_RANGE 8 #define BCM2711_PWM1_DATA 9 #define BCM2711_PWM1_USEFIFO 0x2000 /* Data from FIFO */ #define BCM2711_PWM1_ENABLE 0x0100 /* Channel enable */ #define BCM2711_PWM0_USEFIFO 0x0020 /* Data from FIFO */ #define BCM2711_PWM0_ENABLE 0x0001 /* Channel enable */ #define BCM2711_PWM_ENAB 0x80000000 /* PWM DMA Configuration: DMA Enable (bit 31 set) */ #define BCM2711_GAPO2 0x20 #define BCM2711_GAPO1 0x10 #define BCM2711_RERR1 0x8 #define BCM2711_WERR1 0x4 #define BCM2711_FULL1 0x1 #define ERRORMASK (BCM2711_GAPO2 | BCM2711_GAPO1 | BCM2711_RERR1 | BCM2711_WERR1) #define DMA_CS 0 /* Control/status register offset for DMA channel 0 */ #define DMA_CONBLK_AD 1 #define DMA_EN1 1 << 1 /* Enable DMA engine 1 */ #define DMA_ACTIVE 1 /* Active bit set */ #define DMA_DEST_DREQ 0x40 /* Use DREQ to pace peripheral writes */ #define DMA_PERMAP_1 0x10000 /* PWM1 peripheral for DREQ */ #define DMA_SRC_INC 0x100 /* Increment source address */ volatile unsigned* clk = (void*)CLOCK_BASE; volatile unsigned* pwm = (void*)PWM_BASE; volatile unsigned* dma = (void*)DMA_BASE; volatile unsigned* dmae = (void*)DMA_ENABLE; volatile unsigned* safe = (void*)SAFE_ADDRESS; struct dma_cb { unsigned int ti; unsigned int source_ad; unsigned int dest_ad; unsigned int txfr_len; unsigned int stride; unsigned int nextconbk; unsigned int null1; unsigned int null2; } __attribute__((aligned(32))); struct dma_cb playback_cb; static void playaudio_dma(void) { extern unsigned char _binary_audio_bin_start[]; extern unsigned char _binary_audio_bin_size[]; unsigned int size = (long)&_binary_audio_bin_size; unsigned char *data = &(_binary_audio_bin_start[0]); // Convert data for (int i=0;i 0) drawRect(1, (60 * core) + 1, (val * 3), (60 * core) + 49, col, 1); } void core3_main(void) { unsigned int core3_val = 0; clear_core3(); // Only run once while (1) { wait_msec(0x3FFFF); drawProgress(3, core3_val); if (core3_val < 100) core3_val++; } } void core2_main(void) { unsigned int core2_val = 0; clear_core2(); // Only run once debugstr("Playing on CPU Core #2 using DMA... "); playaudio_dma(); debugstr("done"); debugcrlf(); debugstr("core2_main() running still... "); while (*(dma+DMA_CS) & 0x1) { // Wait for DMA transfer to finish - we could do anything here instead! wait_msec(0x7FFFF); drawProgress(2, core2_val); if (core2_val < 100) core2_val++; } debugstr("done"); drawProgress(2, 100); } void core1_main(void) { clear_core1(); // Only run once drawProgress(1, 50); debugstr("Playing on CPU Core #1... "); playaudio_cpu(); debugstr("done"); debugcrlf(); drawProgress(1, 100); start_core2(core2_main); // Kick it off on core 2 } void core0_main(void) { unsigned int core0_val = 0; while (1) { wait_msec(0x100000); drawProgress(0, core0_val); if (core0_val < 100) core0_val++; } } void main(void) { fb_init(); initProgress(); unsigned int i=0; while (i++<30) debugcrlf(); debugstr("Initialising audio unit... "); audio_init(); debugstr("done"); debugcrlf(); start_core3(core3_main); // Kick it off on core 3 start_core1(core1_main); // Kick it off on core 1 core0_main(); // Loop endlessly }