int gpu_fft_get_host_info(struct GPU_FFT_HOST *info) { void *handle; unsigned (*bcm_host_get_sdram_address)(void); unsigned (*bcm_host_get_peripheral_address)(void); unsigned (*bcm_host_get_peripheral_size)(void); // Pi 1 defaults info->peri_addr = 0x20000000; info->peri_size = 0x01000000; info->mem_flg = GPU_FFT_USE_VC4_L2_CACHE ? 0xC : 0x4; info->mem_map = GPU_FFT_USE_VC4_L2_CACHE ? 0x0 : 0x20000000; // Pi 1 only handle = dlopen("libbcm_host.so", RTLD_LAZY); if (!handle) return -1; *(void **)(&bcm_host_get_sdram_address) = dlsym(handle, "bcm_host_get_sdram_address"); *(void **)(&bcm_host_get_peripheral_address) = dlsym(handle, "bcm_host_get_peripheral_address"); *(void **)(&bcm_host_get_peripheral_size) = dlsym(handle, "bcm_host_get_peripheral_size"); if (bcm_host_get_sdram_address && bcm_host_get_sdram_address() != 0x40000000) { // Pi 2? info->mem_flg = 0x4; // ARM cannot see VC4 L2 on Pi 2 info->mem_map = 0x0; } if (bcm_host_get_peripheral_address) info->peri_addr = bcm_host_get_peripheral_address(); if (bcm_host_get_peripheral_size) info->peri_size = bcm_host_get_peripheral_size(); dlclose(handle); return 0; }
void *blink(int *terminate) { int i, j, k, switchscan, tmp; // Find gpio address (different for Pi 2) ---------- gpio.addr_p = bcm_host_get_peripheral_address() + +0x200000; if (gpio.addr_p == 0x20200000) printf("RPi Plus detected\n"); else printf("RPi 2 detected\n"); // printf("Priority max SCHED_FIFO = %u\n",sched_get_priority_max(SCHED_FIFO) ); // set thread to real time priority ----------------- struct sched_param sp; sp.sched_priority = 98; // maybe 99, 32, 31? if (pthread_setschedparam(pthread_self(), SCHED_FIFO, &sp)) { fprintf(stderr, "warning: failed to set RT priority\n"); } // -------------------------------------------------- if (map_peripheral(&gpio) == -1) { printf("Failed to map the physical GPIO registers into the virtual memory space.\n"); return (void *) -1; } // initialise GPIO (all pins used as inputs, with pull-ups enabled on cols) // INSERT CODE HERE TO SET GPIO 14 AND 15 TO I/O INSTEAD OF ALT 0. // AT THE MOMENT, USE "sudo ./gpio mode 14 in" and "sudo ./gpio mode 15 in". "sudo ./gpio readall" to verify. for (i = 0; i < 8; i++) { // Define ledrows as input INP_GPIO(ledrows[i]); GPIO_CLR = 1 << ledrows[i]; // so go to Low when switched to output } for (i = 0; i < 12; i++) // Define cols as input { INP_GPIO(cols[i]); } for (i = 0; i < 3; i++) // Define rows as input { INP_GPIO(rows[i]); } // BCM2835 ARM Peripherals PDF p 101 & elinux.org/RPi_Low-level_peripherals#Internal_Pull-Ups_.26_Pull-Downs GPIO_PULL = 2; // pull-up short_wait(); // must wait 150 cycles #ifdef SERIALSETUP GPIO_PULLCLK0 = 0x03ffc; // selects GPIO pins 2..13 (frees up serial port on 14 & 15) #else GPIO_PULLCLK0 = 0x0fff0; // selects GPIO pins 4..15 (assumes we avoid pins 2 and 3!) #endif short_wait(); GPIO_PULL = 0; // reset GPPUD register short_wait(); GPIO_PULLCLK0 = 0; // remove clock short_wait(); // probably unnecessary // BCM2835 ARM Peripherals PDF p 101 & elinux.org/RPi_Low-level_peripherals#Internal_Pull-Ups_.26_Pull-Downs GPIO_PULL = 0; // no pull-up no pull-down just float short_wait(); // must wait 150 cycles GPIO_PULLCLK0 = 0x0ff00000; // selects GPIO pins 20..27 short_wait(); GPIO_PULL = 0; // reset GPPUD register short_wait(); GPIO_PULLCLK0 = 0; // remove clock short_wait(); // probably unnecessary // BCM2835 ARM Peripherals PDF p 101 & elinux.org/RPi_Low-level_peripherals#Internal_Pull-Ups_.26_Pull-Downs GPIO_PULL = 0; // no pull-up no pull down just float // not the reason for flashes it seems: //GPIO_PULL = 2; // pull-up - letf in but does not the reason for flashes short_wait(); // must wait 150 cycles GPIO_PULLCLK0 = 0x070000; // selects GPIO pins 16..18 short_wait(); GPIO_PULL = 0; // reset GPPUD register short_wait(); GPIO_PULLCLK0 = 0; // remove clock short_wait(); // probably unnecessary // -------------------------------------------------- printf("\nFP on\n"); while (*terminate == 0) { unsigned phase; // if ((loopcount++ % 500) == 0) printf("1\n"); // visual heart beat // display all phases circular for (phase = 0; phase < GPIOPATTERN_LED_BRIGHTNESS_PHASES; phase++) { // each phase must be eact same duration, so include switch scanning here // the original gpio_ledstatus[8] runs trough all phases volatile uint32_t *gpio_ledstatus = gpiopattern_ledstatus_phases[gpiopattern_ledstatus_phases_readidx][phase]; // prepare for lighting LEDs by setting col pins to output for (i = 0; i < 12; i++) { INP_GPIO(cols[i]); // OUT_GPIO(cols[i]); // Define cols as output } // light up 8 rows of 12 LEDs each for (i = 0; i < 8; i++) { // Toggle columns for this ledrow (which LEDs should be on (CLR = on)) for (k = 0; k < 12; k++) { if ((gpio_ledstatus[i] & (1 << k)) == 0) GPIO_SET = 1 << cols[k]; else GPIO_CLR = 1 << cols[k]; } // Toggle this ledrow on INP_GPIO(ledrows[i]); GPIO_SET = 1 << ledrows[i]; // test for flash problem OUT_GPIO(ledrows[i]); /*test* / GPIO_SET = 1 << ledrows[i]; /**/ nanosleep((struct timespec[] ) { { 0, intervl}}, NULL); // Toggle ledrow off GPIO_CLR = 1 << ledrows[i]; // superstition INP_GPIO(ledrows[i]); usleep(10); // waste of cpu cycles but may help against udn2981 ghosting, not flashes though } //nanosleep ((struct timespec[]){{0, intervl}}, NULL); // test // prepare for reading switches for (i = 0; i < 12; i++) INP_GPIO(cols[i]); // flip columns to input. Need internal pull-ups enabled. // read three rows of switches for (i = 0; i < 3; i++) { INP_GPIO(rows[i]); // GPIO_CLR = 1 << rows[i]; // and output 0V to overrule built-in pull-up from column input pin OUT_GPIO(rows[i]); // turn on one switch row GPIO_CLR = 1 << rows[i]; // and output 0V to overrule built-in pull-up from column input pin nanosleep((struct timespec[] ) { { 0, intervl / 100}}, NULL); // probably unnecessary long wait, maybe put above this loop also switchscan = 0; for (j = 0; j < 12; j++) // 12 switches in each row { tmp = GPIO_READ(cols[j]); if (tmp != 0) switchscan += 1 << j; } INP_GPIO(rows[i]); // stop sinking current from this row of switches gpio_switchstatus[i] = switchscan; } }