Exemple #1
0
/**
 * Map all devices into userspace memory.
 *
 * @param    ws2811  ws2811 instance pointer.
 *
 * @returns  0 on success, -1 otherwise.
 */
static int map_registers(ws2811_t *ws2811)
{
    ws2811_device_t *device = ws2811->device;
    uint32_t dma_addr = dmanum_to_phys(ws2811->dmanum);
    uint32_t base = board_info_peripheral_base_addr();

    if (!dma_addr)
    {
        return -1;
    }

    device->dma = mapmem(dma_addr, sizeof(dma_t));
    if (!device->dma)
    {
        return -1;
    }

    device->pwm = mapmem(PWM_OFFSET + base, sizeof(pwm_t));
    if (!device->pwm)
    {
        return -1;
    }

    device->gpio = mapmem(GPIO_OFFSET + base, sizeof(gpio_t));
    if (!device->gpio)
    {
        return -1;
    }

    device->cm_pwm = mapmem(CM_PWM_OFFSET + base, sizeof(cm_pwm_t));
    if (!device->cm_pwm)
    {
        return -1;
    }

    return 0;
}
Exemple #2
0
void dispmanxtest() {
	DISPMANX_DISPLAY_HANDLE_T display;
	int ret;
	DISPMANX_MODEINFO_T displayinfo;
	DISPMANX_RESOURCE_HANDLE_T res;
	int width = 1024;
	int height = 576;
	uint32_t vc_image_ptr;
	DISPMANX_UPDATE_HANDLE_T update;
	VC_RECT_T dst_rect,src_rect;
	DISPMANX_ELEMENT_HANDLE_T element;

	
	bcm_host_init();
	display = vc_dispmanx_display_open(0);
	ret = vc_dispmanx_display_get_info( display, &displayinfo);
	assert(ret==0);
	printf("display is %dx%d\n",displayinfo.width,displayinfo.height);
	res = vc_dispmanx_resource_create(VC_IMAGE_YUV420,width,height,&vc_image_ptr);
	vc_image_ptr = vc_dispmanx_resource_get_image_handle(res);
	printf("vc_image_ptr %x\n",vc_image_ptr);
	assert(res);
	update = vc_dispmanx_update_start(10);
	assert(update);
	vc_dispmanx_rect_set(&src_rect,0,0,width<<16,height<<16);
	vc_dispmanx_rect_set(&dst_rect,0,(displayinfo.height - height)/2,width-32,height);
	element = vc_dispmanx_element_add(update,display,2000,&dst_rect,res,&src_rect,DISPMANX_PROTECTION_NONE,NULL,NULL,DISPMANX_NO_ROTATE);
	ret = vc_dispmanx_update_submit_sync(update);
	assert(ret==0);
	uint8_t *rawfb = (uint8_t*)mapmem(vc_image_ptr,0x1000);
	for (int i=0; i<0x100; i++) {
		printf("%02x ",rawfb[i]);
	}
	printf("\n");
	unmapmem(rawfb,0x1000);
	puts("sleeping");
	sleep(10);
	update = vc_dispmanx_update_start(10);
	assert(update);
	ret = vc_dispmanx_element_remove(update,element);
	assert(ret==0);
	ret = vc_dispmanx_update_submit_sync(update);
	assert(ret==0);
	ret = vc_dispmanx_resource_delete(res);
	assert(ret==0);
	ret = vc_dispmanx_display_close(display);
	assert(ret==0);
}
Exemple #3
0
// Execute a nop control list to prove that we have contol.
void testControlLists() {
// First we allocate and map some videocore memory to build our control list in.

  // ask the blob to allocate us 256 bytes with 4k alignment, zero it.
  unsigned int handle = mem_alloc(mbox, 0x100, 0x1000, MEM_FLAG_COHERENT | MEM_FLAG_ZERO);
  if (!handle) {
    printf("Error: Unable to allocate memory");
    return;
  }
  // ask the blob to lock our memory at a single location at give is that address.
  uint32_t bus_addr = mem_lock(mbox, handle); 
  // map that address into our local address space.
  uint8_t *list = (uint8_t*) mapmem(bus_addr, 0x100);

// Now we construct our control list.
  // 255 nops, with a halt somewhere in the middle
  for(int i = 0; i < 0xff; i++) {
    list[i] = 1; // NOP
  }
  list[0xbb] = 0; // Halt.

// And then we setup the v3d pipeline to execute the control list.
  printf("V3D_CT0CS: 0x%08x\n", v3d[V3D_CT0CS]); 
  printf("Start Address: 0x%08x\n", bus_addr);
  // Current Address = start of our list (bus address)
  v3d[V3D_CT0CA] = bus_addr;
  // End Address = just after the end of our list (bus address) 
  // This also starts execution.
  v3d[V3D_CT0EA] = bus_addr + 0x100;
  
  // print status while running
  printf("V3D_CT0CS: 0x%08x, Address: 0x%08x\n", v3d[V3D_CT0CS], v3d[V3D_CT0CA]);

  // Wait a second to be sure the contorl list execution has finished
  while(v3d[V3D_CT0CS] & 0x20);

  // print the status again.
  printf("V3D_CT0CS: 0x%08x, Address: 0x%08x\n", v3d[V3D_CT0CS], v3d[V3D_CT0CA]);

// Release memory;
  unmapmem((void *) list, 0x100);
  mem_unlock(mbox, handle);
  mem_free(mbox, handle);
}
Exemple #4
0
char InitDma(void *FunctionTerminate)
{
	//printf("Init DMA\n");
	
	// Catch all signals possible - it is vital we kill the DMA engine
	// on process exit!
	int i;
	for (i = 0; i < 64; i++) {
		struct sigaction sa;

		memset(&sa, 0, sizeof(sa));
		sa.sa_handler = FunctionTerminate;//terminate;
		sigaction(i, &sa, NULL);
	}

	NUM_SAMPLES = NUM_SAMPLES_MAX;

	/* Use the mailbox interface to the VC to ask for physical memory */
	/*unlink(MBFILE);
	if (mknod(MBFILE, S_IFCHR|0600, makedev(100, 0)) < 0)
	{
		printf("Failed to create mailbox device\n");
		return 0;
	}
	*/
	mbox.handle = mbox_open();
	if (mbox.handle < 0)
	{
		printf("Failed to open mailbox\n");
		return(0);
	}
	
	mbox.mem_ref = mem_alloc(mbox.handle, NUM_PAGES* PAGE_SIZE, PAGE_SIZE, mem_flag);
	/* TODO: How do we know that succeeded? */
	//printf("mem_ref %x\n", mbox.mem_ref);
	mbox.bus_addr = mem_lock(mbox.handle, mbox.mem_ref);
	//printf("bus_addr = %x\n", mbox.bus_addr);
	mbox.virt_addr = mapmem(BUS_TO_PHYS(mbox.bus_addr), NUM_PAGES* PAGE_SIZE);
	//printf("virt_addr %p\n", mbox.virt_addr);
	virtbase = (uint32_t *)mbox.virt_addr;
	//printf("virtbase %p\n", virtbase);
	return(1);
	
}
Exemple #5
0
int main(int argc, char **argv) {
  mbox = mbox_open();

  // The blob now has this nice handy call which powers up the v3d pipeline.
  qpu_enable(mbox, 1);

  // map v3d's registers into our address space.
  v3d = (unsigned *) mapmem(0x20c00000, 0x1000);

  if(v3d[V3D_IDENT0] != 0x02443356) { // Magic number.
    printf("Error: V3D pipeline isn't powered up and accessable.\n");
    exit(-1);
  }

  // We now have access to the v3d registers, we should do something.
  testTriangle();

  return 0;
}
Exemple #6
0
/* Initialise this library. */
int bcm2835_init(void)
{
    int  memfd;
    int  ok;
    FILE *fp;

    if (debug) 
    {
        bcm2835_peripherals = (uint32_t*)BCM2835_PERI_BASE;

	bcm2835_pads = bcm2835_peripherals + BCM2835_GPIO_PADS/4;
	bcm2835_clk  = bcm2835_peripherals + BCM2835_CLOCK_BASE/4;
	bcm2835_gpio = bcm2835_peripherals + BCM2835_GPIO_BASE/4;
	bcm2835_pwm  = bcm2835_peripherals + BCM2835_GPIO_PWM/4;
	bcm2835_spi0 = bcm2835_peripherals + BCM2835_SPI0_BASE/4;
	bcm2835_bsc0 = bcm2835_peripherals + BCM2835_BSC0_BASE/4;
	bcm2835_bsc1 = bcm2835_peripherals + BCM2835_BSC1_BASE/4;
	bcm2835_st   = bcm2835_peripherals + BCM2835_ST_BASE/4;
	return 1; /* Success */
    }

    /* Figure out the base and size of the peripheral address block
    // using the device-tree. Required for RPi2, optional for RPi 1
    */
    if ((fp = fopen(BMC2835_RPI2_DT_FILENAME , "rb")))
    {
        unsigned char buf[4];
	fseek(fp, BMC2835_RPI2_DT_PERI_BASE_ADDRESS_OFFSET, SEEK_SET);
	if (fread(buf, 1, sizeof(buf), fp) == sizeof(buf))
	  bcm2835_peripherals_base = (uint32_t *)(buf[0] << 24 | buf[1] << 16 | buf[2] << 8 | buf[3] << 0);
	fseek(fp, BMC2835_RPI2_DT_PERI_SIZE_OFFSET, SEEK_SET);
	if (fread(buf, 1, sizeof(buf), fp) == sizeof(buf))
	  bcm2835_peripherals_size = (buf[0] << 24 | buf[1] << 16 | buf[2] << 8 | buf[3] << 0);
	fclose(fp);
    }
    /* else we are prob on RPi 1 with BCM2835, and use the hardwired defaults */

    /* Now get ready to map the peripherals block 
     * If we are not root, try for the new /dev/gpiomem interface and accept
     * the fact that we can only access GPIO
     * else try for the /dev/mem interface and get access to everything
     */
    memfd = -1;
    ok = 0;
    if (geteuid() == 0)
    {
      /* Open the master /dev/mem device */
      if ((memfd = open("/dev/mem", O_RDWR | O_SYNC) ) < 0) 
	{
	  fprintf(stderr, "bcm2835_init: Unable to open /dev/mem: %s\n",
		  strerror(errno)) ;
	  goto exit;
	}
      
      /* Base of the peripherals block is mapped to VM */
      bcm2835_peripherals = mapmem("gpio", bcm2835_peripherals_size, memfd, (uint32_t)bcm2835_peripherals_base);
      if (bcm2835_peripherals == MAP_FAILED) goto exit;
      
      /* Now compute the base addresses of various peripherals, 
      // which are at fixed offsets within the mapped peripherals block
      // Caution: bcm2835_peripherals is uint32_t*, so divide offsets by 4
      */
      bcm2835_gpio = bcm2835_peripherals + BCM2835_GPIO_BASE/4;
      bcm2835_pwm  = bcm2835_peripherals + BCM2835_GPIO_PWM/4;
      bcm2835_clk  = bcm2835_peripherals + BCM2835_CLOCK_BASE/4;
      bcm2835_pads = bcm2835_peripherals + BCM2835_GPIO_PADS/4;
      bcm2835_spi0 = bcm2835_peripherals + BCM2835_SPI0_BASE/4;
      bcm2835_bsc0 = bcm2835_peripherals + BCM2835_BSC0_BASE/4; /* I2C */
      bcm2835_bsc1 = bcm2835_peripherals + BCM2835_BSC1_BASE/4; /* I2C */
      bcm2835_st   = bcm2835_peripherals + BCM2835_ST_BASE/4;
      
      ok = 1;
    }
    else
    {
      /* Not root, try /dev/gpiomem */
      /* Open the master /dev/mem device */
      if ((memfd = open("/dev/gpiomem", O_RDWR | O_SYNC) ) < 0) 
	{
	  fprintf(stderr, "bcm2835_init: Unable to open /dev/gpiomem: %s\n",
		  strerror(errno)) ;
	  goto exit;
	}
      
      /* Base of the peripherals block is mapped to VM */
      bcm2835_peripherals_base = 0;
      bcm2835_peripherals = mapmem("gpio", bcm2835_peripherals_size, memfd, (uint32_t)bcm2835_peripherals_base);
      if (bcm2835_peripherals == MAP_FAILED) goto exit;
      bcm2835_gpio = bcm2835_peripherals;
      ok = 1;
    }

exit:
    if (memfd >= 0)
        close(memfd);

    if (!ok)
	bcm2835_close();

    return ok;
}
Exemple #7
0
int
main(int argc, char **argv)
{
	parseargs(argc, argv);
	mbox.handle = mbox_open();
	if (mbox.handle < 0)
		fatal("Failed to open mailbox\n");
	unsigned mbox_board_rev = get_board_revision(mbox.handle);
	printf("MBox Board Revision: %#x\n", mbox_board_rev);
	get_model(mbox_board_rev);
	unsigned mbox_dma_channels = get_dma_channels(mbox.handle);
	printf("DMA Channels Info: %#x, using DMA Channel: %d\n", mbox_dma_channels, DMA_CHAN_NUM);

	printf("Using hardware:                 %5s\n", delay_hw == DELAY_VIA_PWM ? "PWM" : "PCM");
	printf("Number of channels:             %5d\n", (int)num_channels);
	printf("PWM frequency:               %5d Hz\n", 1000000/CYCLE_TIME_US);
	printf("PWM steps:                      %5d\n", NUM_SAMPLES);
	printf("Maximum period (100  %%):      %5dus\n", CYCLE_TIME_US);
	printf("Minimum period (%1.3f%%):      %5dus\n", 100.0*SAMPLE_US / CYCLE_TIME_US, SAMPLE_US);
	printf("DMA Base:                  %#010x\n", DMA_BASE);

	setup_sighandlers();

	/* map the registers for all DMA Channels */
	dma_virt_base = map_peripheral(DMA_BASE, (DMA_CHAN_SIZE * (DMA_CHAN_MAX + 1)));
	/* set dma_reg to point to the DMA Channel we are using */
	dma_reg = dma_virt_base + DMA_CHAN_NUM * (DMA_CHAN_SIZE / sizeof(dma_reg));
	pwm_reg = map_peripheral(PWM_BASE, PWM_LEN);
	pcm_reg = map_peripheral(PCM_BASE, PCM_LEN);
	clk_reg = map_peripheral(CLK_BASE, CLK_LEN);
	gpio_reg = map_peripheral(GPIO_BASE, GPIO_LEN);

	/* Use the mailbox interface to the VC to ask for physical memory */
	mbox.mem_ref = mem_alloc(mbox.handle, NUM_PAGES * PAGE_SIZE, PAGE_SIZE, mem_flag);
	/* TODO: How do we know that succeeded? */
	dprintf("mem_ref %u\n", mbox.mem_ref);
	mbox.bus_addr = mem_lock(mbox.handle, mbox.mem_ref);
	dprintf("bus_addr = %#x\n", mbox.bus_addr);
	mbox.virt_addr = mapmem(BUS_TO_PHYS(mbox.bus_addr), NUM_PAGES * PAGE_SIZE);
	dprintf("virt_addr %p\n", mbox.virt_addr);

	if ((unsigned long)mbox.virt_addr & (PAGE_SIZE-1))
		fatal("pi-blaster: Virtual address is not page aligned\n");

	/* we are done with the mbox */
	mbox_close(mbox.handle);
	mbox.handle = -1;
	
	//fatal("TempFatal\n");

	init_ctrl_data();
	init_hardware();
	init_channel_pwm();
	// Init pin2gpio array with 0/false values to avoid locking all of them as PWM.
	init_pin2gpio();
	// Only calls update_pwm after ctrl_data calculates the pin mask to unlock all pins on start.
	init_pwm();
	unlink(DEVFILE);
	if (mkfifo(DEVFILE, 0666) < 0)
		fatal("pi-blaster: Failed to create %s: %m\n", DEVFILE);
	if (chmod(DEVFILE, 0666) < 0)
		fatal("pi-blaster: Failed to set permissions on %s: %m\n", DEVFILE);

	printf("Initialised, ");
	if (daemonize) {
		if (daemon(0,1) < 0) 
			fatal("pi-blaster: Failed to daemonize process: %m\n");
		else
			printf("Daemonized, ");
	}
	printf("Reading %s.\n", DEVFILE);

	go_go_go();

	return 0;
}
/**
 * Allocate and initialize memory, buffers, pages, PWM, DMA, and GPIO.
 *
 * @param    ws2811  ws2811 instance pointer.
 *
 * @returns  0 on success, -1 otherwise.
 */
int ws2811_init(ws2811_t *ws2811)
{
    ws2811_device_t *device = NULL;
    int chan;

    // Zero mbox; non-zero values indicate action needed on cleanup
    memset(&mbox, 0, sizeof(mbox));

    ws2811->device = malloc(sizeof(*ws2811->device));
    if (!ws2811->device)
    {
        return -1;
    }
    device = ws2811->device;

    // Determine how much physical memory we need for DMA
    mbox.size = PWM_BYTE_COUNT(max_channel_led_count(ws2811), ws2811->freq) +
               + sizeof(dma_cb_t);
    // Round up to page size multiple
    mbox.size = (mbox.size + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1);

    // Use the mailbox interface to request memory from the VideoCore
    // We specifiy (-1) for the handle rather than calling mbox_open()
    // so multiple users can share the resource.
    mbox.handle = -1; // mbox_open();
    mbox.mem_ref = mem_alloc(mbox.handle, mbox.size, PAGE_SIZE,
            board_info_sdram_address() == 0x40000000 ? 0xC : 0x4);
    if (mbox.mem_ref == (unsigned) ~0)
    {
       return -1;
    }
    mbox.bus_addr = mem_lock(mbox.handle, mbox.mem_ref);
    if (mbox.bus_addr == (unsigned) ~0)
    {
       mem_free(mbox.handle, mbox.size);
       return -1;
    }
    mbox.virt_addr = mapmem(BUS_TO_PHYS(mbox.bus_addr), mbox.size);

    // Initialize all pointers to NULL.  Any non-NULL pointers will be freed on cleanup.
    device->pwm_raw = NULL;
    device->dma_cb = NULL;
    for (chan = 0; chan < RPI_PWM_CHANNELS; chan++)
    {
        ws2811->channel[chan].leds = NULL;
    }

    // Allocate the LED buffers
    for (chan = 0; chan < RPI_PWM_CHANNELS; chan++)
    {
        ws2811_channel_t *channel = &ws2811->channel[chan];

        channel->leds = malloc(sizeof(ws2811_led_t) * channel->count);
        if (!channel->leds)
        {
            goto err;
        }

        memset(channel->leds, 0, sizeof(ws2811_led_t) * channel->count);
    }

    device->dma_cb = (dma_cb_t *)mbox.virt_addr;
    device->pwm_raw = (uint8_t *)mbox.virt_addr + sizeof(dma_cb_t);

    pwm_raw_init(ws2811);

    memset((dma_cb_t *)device->dma_cb, 0, sizeof(dma_cb_t));

    // Cache the DMA control block bus address
    device->dma_cb_addr = addr_to_bus(device->dma_cb);

    // Map the physical registers into userspace
    if (map_registers(ws2811))
    {
        goto err;
    }

    // Initialize the GPIO pins
    if (gpio_init(ws2811))
    {
        unmap_registers(ws2811);
        goto err;
    }

    // Setup the PWM, clocks, and DMA
    if (setup_pwm(ws2811))
    {
        unmap_registers(ws2811);
        goto err;
    }

    return 0;

err:
    ws2811_cleanup(ws2811);

    return -1;
}
Exemple #9
0
char InitDma(void *FunctionTerminate)
{
    DMA_CHANNEL=4;
    if (system("rm -f linuxversion.txt") != 0) {
        fprintf(stderr, "rm failed\n");
    }
    if (system("uname -r >> linuxversion.txt") != 0) {
        fprintf(stderr, "uname failed\n");
    }
    char *line = NULL;
    size_t size;
//	int fLinux=open("Flinuxversion.txt", "r');
    FILE * flinux=fopen("linuxversion.txt", "r");
    if (getline(&line, &size, flinux) == -1)
    {
        printf("Could no get Linux version\n");
    }
    else
    {
        if(line[0]=='3')
        {
            printf("Wheezy\n");
            DMA_CHANNEL=DMA_CHANNEL_WHEEZY;
        }

        if(line[0]=='4')
        {
            printf("Jessie\n");
            DMA_CHANNEL=DMA_CHANNEL_JESSIE;
        }

    }
    //printf("Init DMA\n");

    // Catch all signals possible - it is vital we kill the DMA engine
    // on process exit!
    int i;
    for (i = 0; i < 64; i++) {
        struct sigaction sa;

        memset(&sa, 0, sizeof(sa));
        sa.sa_handler = FunctionTerminate;//terminate;
        sigaction(i, &sa, NULL);
    }

    //NUM_SAMPLES = NUM_SAMPLES_MAX;

    /* Use the mailbox interface to the VC to ask for physical memory */
    /*
    unlink(MBFILE);
    if (mknod(MBFILE, S_IFCHR|0600, makedev(100, 0)) < 0)
    {
    	printf("Failed to create mailbox device\n");
    	return 0;
    }*/
    mbox.handle = mbox_open();
    if (mbox.handle < 0)
    {
        printf("Failed to open mailbox\n");
        return(0);
    }
    mbox.mem_ref = mem_alloc(mbox.handle, NUM_PAGES* PAGE_SIZE, PAGE_SIZE, mem_flag);
    /* TODO: How do we know that succeeded? */
    //printf("mem_ref %x\n", mbox.mem_ref);
    mbox.bus_addr = mem_lock(mbox.handle, mbox.mem_ref);
    //printf("bus_addr = %x\n", mbox.bus_addr);
    mbox.virt_addr = mapmem(BUS_TO_PHYS(mbox.bus_addr), NUM_PAGES* PAGE_SIZE);
    //printf("virt_addr %p\n", mbox.virt_addr);
    virtbase = (uint8_t *)((uint32_t *)mbox.virt_addr);
    //printf("virtbase %p\n", virtbase);
    return(1);

}
Exemple #10
0
/**
 * Allocate and initialize memory, buffers, pages, PWM, DMA, and GPIO.
 *
 * @param    ws2811  ws2811 instance pointer.
 *
 * @returns  0 on success, -1 otherwise.
 */
int ws2811_init(ws2811_t *ws2811)
{
    ws2811_device_t *device;
    const rpi_hw_t *rpi_hw;
    int chan;

    ws2811->rpi_hw = rpi_hw_detect();
    if (!ws2811->rpi_hw)
    {
        return -1;
    }
    rpi_hw = ws2811->rpi_hw;

    ws2811->device = malloc(sizeof(*ws2811->device));
    if (!ws2811->device)
    {
        return -1;
    }
    device = ws2811->device;

    // Determine how much physical memory we need for DMA
    device->mbox.size = PWM_BYTE_COUNT(max_channel_led_count(ws2811), ws2811->freq) +
                        sizeof(dma_cb_t);
    // Round up to page size multiple
    device->mbox.size = (device->mbox.size + (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1);

    device->mbox.handle = mbox_open();
    if (device->mbox.handle == -1)
    {
        return -1;
    }

    device->mbox.mem_ref = mem_alloc(device->mbox.handle, device->mbox.size, PAGE_SIZE,
                                     rpi_hw->videocore_base == 0x40000000 ? 0xC : 0x4);
    if (device->mbox.mem_ref == 0)
    {
       return -1;
    }

    device->mbox.bus_addr = mem_lock(device->mbox.handle, device->mbox.mem_ref);
    if (device->mbox.bus_addr == (uint32_t) ~0UL)
    {
       mem_free(device->mbox.handle, device->mbox.size);
       return -1;
    }
    device->mbox.virt_addr = mapmem(BUS_TO_PHYS(device->mbox.bus_addr), device->mbox.size);

    // Initialize all pointers to NULL.  Any non-NULL pointers will be freed on cleanup.
    device->pwm_raw = NULL;
    device->dma_cb = NULL;
    for (chan = 0; chan < RPI_PWM_CHANNELS; chan++)
    {
        ws2811->channel[chan].leds = NULL;
    }

    // Allocate the LED buffers
    for (chan = 0; chan < RPI_PWM_CHANNELS; chan++)
    {
        ws2811_channel_t *channel = &ws2811->channel[chan];

        channel->leds = malloc(sizeof(ws2811_led_t) * channel->count);
        if (!channel->leds)
        {
            goto err;
        }

        memset(channel->leds, 0, sizeof(ws2811_led_t) * channel->count);

        if (!channel->strip_type)
        {
          channel->strip_type=WS2811_STRIP_RGB;
        }
    }

    device->dma_cb = (dma_cb_t *)device->mbox.virt_addr;
    device->pwm_raw = (uint8_t *)device->mbox.virt_addr + sizeof(dma_cb_t);

    pwm_raw_init(ws2811);

    memset((dma_cb_t *)device->dma_cb, 0, sizeof(dma_cb_t));

    // Cache the DMA control block bus address
    device->dma_cb_addr = addr_to_bus(device, device->dma_cb);

    // Map the physical registers into userspace
    if (map_registers(ws2811))
    {
        goto err;
    }

    // Initialize the GPIO pins
    if (gpio_init(ws2811))
    {
        unmap_registers(ws2811);
        goto err;
    }

    // Setup the PWM, clocks, and DMA
    if (setup_pwm(ws2811))
    {
        unmap_registers(ws2811);
        goto err;
    }

    return 0;

err:
    ws2811_cleanup(ws2811);

    return -1;
}
Exemple #11
0
int
EtherInit(unsigned char *myadr)
{
	uint32_t pcicsr;
	uint16_t val;
	volatile struct ex_upd *upd;
#ifndef _STANDALONE
	uint32_t id;
#endif

	if (pcicheck()) {
		printf("pcicheck failed\n");
		return 0;
	}
#ifndef _STANDALONE
	pcicfgread(&mytag, 0, &id);
#endif
	for (excard = &excards[0]; excard->did != -1; excard++) {
#ifdef _STANDALONE
		if (pcifinddev(0x10b7, excard->did, &mytag) == 0)
			goto found;
#else
		if (id == (0x10b7 | (excard->did << 16)))
			goto found;
#endif
	}
	printf("no ex\n");
	return 0;

found:
	pcicfgread(&mytag, 0x10, &iobase);
	iobase &= ~3;

#ifndef _STANDALONE
	dmamem = mapmem(DMABASE, DMASIZE);
	if (!dmamem)
		return 0;
#endif

	/* enable bus mastering in PCI command register */
	if (pcicfgread(&mytag, 0x04, (int *)&pcicsr)
	    || pcicfgwrite(&mytag, 0x04, pcicsr | 4)) {
		printf("cannot enable DMA\n");
		return 0;
	}

	ex_reset();

	if (excard->mii)
		ether_medium = ETHERMEDIUM_MII;
	else {
		ex_probemedia();
		if (ether_medium < 0)
			return 0;
	}

	val = ex_read_eeprom(EEPROM_OEM_ADDR0);
	myethaddr[0] = val >> 8;
	myethaddr[1] = val & 0xff;
	val = ex_read_eeprom(EEPROM_OEM_ADDR1);
	myethaddr[2] = val >> 8;
	myethaddr[3] = val & 0xff;
	val = ex_read_eeprom(EEPROM_OEM_ADDR2);
	myethaddr[4] = val >> 8;
	myethaddr[5] = val & 0xff;
	memcpy(myadr, myethaddr, 6);

	upd = RECVBUF_VIRT;
	upd->upd_nextptr = RECVBUF_PHYS;
	upd->upd_pktstatus = 1500;
	upd->upd_frags[0].fr_addr = RECVBUF_PHYS + 100;
	upd->upd_frags[0].fr_len = 1500 | EX_FR_LAST;

	ex_init();

#if defined(_STANDALONE) && !defined(SUPPORT_NO_NETBSD)
	strncpy(bi_netif.ifname, "ex", sizeof(bi_netif.ifname));
	bi_netif.bus = BI_BUS_PCI;
	bi_netif.addr.tag = mytag;

	BI_ADD(&bi_netif, BTINFO_NETIF, sizeof(bi_netif));
#endif

	return 1;
}
Exemple #12
0
int main(int argc, char *argv[]) {

	int mb = mbox_open();

	/* Enable QPU for execution */
	int qpu_enabled = !qpu_enable(mb, 1);
	if (!qpu_enabled) {
		printf("Unable to enable QPU.  Check your firmware is latest.");
		goto cleanup;
	}

	/* Allocate GPU memory and map it into ARM address space */
	unsigned size = 4096;
	unsigned align = 4096;
    	unsigned handle = mem_alloc(mb, size, align, GPU_MEM_FLG);
	if (!handle) {
		printf("Failed to allocate GPU memory.");
		goto cleanup;
	}
	void *gpu_pointer = (void *)mem_lock(mb, handle);
	void *arm_pointer = mapmem((unsigned)gpu_pointer+GPU_MEM_MAP, size);

	unsigned *p = (unsigned *)arm_pointer;

	/*
	   +---------------+ <----+
	   |  QPU Code     |      |
	   |  ...          |      |
	   +---------------+ <--+ |
	   |  Uniforms     |    | |
	   +---------------+    | |
	   |  QPU0 Uniform -----+ |
	   |  QPU0 Start   -------+
	   |  ...                 |
	   |  QPUn Uniform        |
	   |  QPUn PC      -------+
	   +---------------+
	*/

	/* Copy QPU program into GPU memory */
	unsigned *qpu_code = p;
	memcpy(p, program, sizeof program);
	p += (sizeof program)/(sizeof program[0]);

	/* Build Uniforms */
	unsigned *qpu_uniform = p;
	*p++ = 1;
	
	/* Build QPU Launch messages */
	unsigned *qpu_msg = p;
	*p++ = as_gpu_address(qpu_uniform);
	*p++ = as_gpu_address(qpu_code);

	int i;
	for (i=0; i<16+1+2; i++) {
		printf("%08x: %08x\n", gpu_pointer+i*4, ((unsigned *)arm_pointer)[i]);
	}
	printf("qpu exec %08x\n", gpu_pointer + ((void *)qpu_msg - arm_pointer));

	/* Launch QPU program and block till its done */
    	unsigned r = execute_qpu(mb, GPU_QPUS, as_gpu_address(qpu_msg), 1, 10000);
	printf("%d\n", r);

cleanup:
	/* Release GPU memory */
	if (arm_pointer) {
		unmapmem(arm_pointer, size);
	}
    	if (handle) {
		mem_unlock(mb, handle);
    		mem_free(mb, handle);
	}
	
	/* Release QPU */
	if (qpu_enabled) {
	    	qpu_enable(mb, 0);
	}
	
	/* Release mailbox */
	mbox_close(mb);

}
Exemple #13
0
// Initialise this library.
int bcm2835_init(void)
{
    struct timeval tv ;
    if (debug) 
    {
        bcm2835_peripherals = (uint32_t*)BCM2835_PERI_BASE;

	bcm2835_pads = bcm2835_peripherals + BCM2835_GPIO_PADS;
	bcm2835_clk  = bcm2835_peripherals + BCM2835_CLOCK_BASE;
	bcm2835_gpio = bcm2835_peripherals + BCM2835_GPIO_BASE;
	bcm2835_pwm  = bcm2835_peripherals + BCM2835_GPIO_PWM;
	bcm2835_spi0 = bcm2835_peripherals + BCM2835_SPI0_BASE;
	bcm2835_bsc0 = bcm2835_peripherals + BCM2835_BSC0_BASE;
	bcm2835_bsc1 = bcm2835_peripherals + BCM2835_BSC1_BASE;
	bcm2835_st   = bcm2835_peripherals + BCM2835_ST_BASE;
	return 1; // Success
    }

    // Figure out the base and size of the peripheral address block, based on whether we are on a RPI2 or not,
    // using the device-tree
    FILE *fp = fopen(BMC2835_RPI2_DT_FILENAME , "rb");
    if (fp)
    {
        unsigned char buf[4];
	fseek(fp, BMC2835_RPI2_DT_PERI_BASE_ADDRESS_OFFSET, SEEK_SET);
	if (fread(buf, 1, sizeof(buf), fp) == sizeof(buf))
	  bcm2835_peripherals_base = (uint32_t *)(buf[0] << 24 | buf[1] << 16 | buf[2] << 8 | buf[3] << 0);
	fseek(fp, BMC2835_RPI2_DT_PERI_SIZE_OFFSET, SEEK_SET);
	if (fread(buf, 1, sizeof(buf), fp) == sizeof(buf))
	  bcm2835_peripherals_size = (buf[0] << 24 | buf[1] << 16 | buf[2] << 8 | buf[3] << 0);
	fclose(fp);
    }
    // else we are prob on RPi 1 with BCM2835, and use the hardwired defaults

    // Now get ready to map the peripherals block
    int memfd = -1;
    int ok = 0;
    // Open the master /dev/memory device
    if ((memfd = open("/dev/mem", O_RDWR | O_SYNC) ) < 0) 
    {
	fprintf(stderr, "bcm2835_init: Unable to open /dev/mem: %s\n",
		strerror(errno)) ;
	goto exit;
    }
	
    // Base of the peripherals block is mapped to VM
    bcm2835_peripherals = (uint32_t *)mapmem("gpio", bcm2835_peripherals_size, memfd, (uint32_t)bcm2835_peripherals_base);
    if (bcm2835_peripherals == MAP_FAILED) goto exit;

    // Now compute the base addresses of various peripherals, which are at fixed offsets within the mapped peripherals block
    bcm2835_gpio = bcm2835_peripherals + BCM2835_GPIO_BASE;
    bcm2835_pwm  = bcm2835_peripherals + BCM2835_GPIO_PWM;
    bcm2835_clk  = bcm2835_peripherals + BCM2835_CLOCK_BASE;
    bcm2835_pads = bcm2835_peripherals + BCM2835_GPIO_PADS;
    bcm2835_spi0 = bcm2835_peripherals + BCM2835_SPI0_BASE;
    bcm2835_bsc0 = bcm2835_peripherals + BCM2835_BSC0_BASE; // I2C
    bcm2835_bsc1 = bcm2835_peripherals + BCM2835_BSC1_BASE; // I2C
    bcm2835_st   = bcm2835_peripherals + BCM2835_ST_BASE;

    ok = 1;

exit:
    if (memfd >= 0)
        close(memfd);

    if (!ok)
	bcm2835_close();

	gettimeofday (&tv, NULL) ;
	epoch = (tv.tv_sec * 1000000 + tv.tv_usec) / 1000 ;

    return ok;
}
Exemple #14
0
// Render a single triangle to memory.
void testTriangle() {
// Like above, we allocate/lock/map some videocore memory
  // I'm just shoving everything in a single buffer because I'm lazy
  // 8Mb, 4k alignment
  unsigned int handle = mem_alloc(mbox, 0x800000, 0x1000, MEM_FLAG_COHERENT | MEM_FLAG_ZERO);
  if (!handle) {
    printf("Error: Unable to allocate memory");
    return;
  }
  uint32_t bus_addr = mem_lock(mbox, handle); 
  uint8_t *list = (uint8_t*) mapmem(bus_addr, 0x800000);

  uint8_t *p = list;

// Configuration stuff
  // Tile Binning Configuration.
  //   Tile state data is 48 bytes per tile, I think it can be thrown away
  //   as soon as binning is finished.
  addbyte(&p, 112);
  addword(&p, bus_addr + 0x6200); // tile allocation memory address
  addword(&p, 0x8000); // tile allocation memory size
  addword(&p, bus_addr + 0x100); // Tile state data address
  addbyte(&p, 30); // 1920/64
  addbyte(&p, 17); // 1080/64 (16.875)
  addbyte(&p, 0x04); // config

  // Start tile binning.
  addbyte(&p, 6);

  // Primitive type
  addbyte(&p, 56);
  addbyte(&p, 0x32); // 16 bit triangle

  // Clip Window
  addbyte(&p, 102);
  addshort(&p, 0);
  addshort(&p, 0);
  addshort(&p, 1920); // width
  addshort(&p, 1080); // height

  // State
  addbyte(&p, 96);
  addbyte(&p, 0x03); // enable both foward and back facing polygons
  addbyte(&p, 0x00); // depth testing disabled
  addbyte(&p, 0x02); // enable early depth write

  // Viewport offset
  addbyte(&p, 103);
  addshort(&p, 0);
  addshort(&p, 0);

// The triangle
  // No Vertex Shader state (takes pre-transformed vertexes, 
  // so we don't have to supply a working coordinate shader to test the binner.
  addbyte(&p, 65);
  addword(&p, bus_addr + 0x80); // Shader Record

  // primitive index list
  addbyte(&p, 32);
  addbyte(&p, 0x04); // 8bit index, trinagles
  addword(&p, 3); // Length
  addword(&p, bus_addr + 0x70); // address
  addword(&p, 2); // Maximum index

// End of bin list
  // Flush
  addbyte(&p, 5);
  // Nop
  addbyte(&p, 1);
  // Halt
  addbyte(&p, 0);

  int length = p - list;
  assert(length < 0x80);

// Shader Record
  p = list + 0x80;
  addbyte(&p, 0x01); // flags
  addbyte(&p, 6*4); // stride
  addbyte(&p, 0xcc); // num uniforms (not used)
  addbyte(&p, 3); // num varyings
  addword(&p, bus_addr + 0xfe00); // Fragment shader code
  addword(&p, bus_addr + 0xff00); // Fragment shader uniforms
  addword(&p, bus_addr + 0xa0); // Vertex Data

// Vertex Data
  p = list + 0xa0;
  // Vertex: Top, red
  addshort(&p, (1920/2) << 4); // X in 12.4 fixed point
  addshort(&p, 200 << 4); // Y in 12.4 fixed point
  addfloat(&p, 1.0f); // Z
  addfloat(&p, 1.0f); // 1/W
  addfloat(&p, 1.0f); // Varying 0 (Red)
  addfloat(&p, 0.0f); // Varying 1 (Green)
  addfloat(&p, 0.0f); // Varying 2 (Blue)

  // Vertex: bottom left, Green
  addshort(&p, 560 << 4); // X in 12.4 fixed point
  addshort(&p, 800 << 4); // Y in 12.4 fixed point
  addfloat(&p, 1.0f); // Z
  addfloat(&p, 1.0f); // 1/W
  addfloat(&p, 0.0f); // Varying 0 (Red)
  addfloat(&p, 1.0f); // Varying 1 (Green)
  addfloat(&p, 0.0f); // Varying 2 (Blue)

  // Vertex: bottom right, Blue
  addshort(&p, 1360 << 4); // X in 12.4 fixed point
  addshort(&p, 800 << 4); // Y in 12.4 fixed point
  addfloat(&p, 1.0f); // Z
  addfloat(&p, 1.0f); // 1/W
  addfloat(&p, 0.0f); // Varying 0 (Red)
  addfloat(&p, 0.0f); // Varying 1 (Green)
  addfloat(&p, 1.0f); // Varying 2 (Blue)

// Vertex list
  p = list + 0x70;
  addbyte(&p, 0); // top
  addbyte(&p, 1); // bottom left
  addbyte(&p, 2); // bottom right

// fragment shader
  p = list + 0xfe00;
  addword(&p, 0x958e0dbf);
  addword(&p, 0xd1724823); /* mov r0, vary; mov r3.8d, 1.0 */
  addword(&p, 0x818e7176); 
  addword(&p, 0x40024821); /* fadd r0, r0, r5; mov r1, vary */
  addword(&p, 0x818e7376); 
  addword(&p, 0x10024862); /* fadd r1, r1, r5; mov r2, vary */
  addword(&p, 0x819e7540); 
  addword(&p, 0x114248a3); /* fadd r2, r2, r5; mov r3.8a, r0 */
  addword(&p, 0x809e7009); 
  addword(&p, 0x115049e3); /* nop; mov r3.8b, r1 */
  addword(&p, 0x809e7012); 
  addword(&p, 0x116049e3); /* nop; mov r3.8c, r2 */
  addword(&p, 0x159e76c0); 
  addword(&p, 0x30020ba7); /* mov tlbc, r3; nop; thrend */
  addword(&p, 0x009e7000);
  addword(&p, 0x100009e7); /* nop; nop; nop */
  addword(&p, 0x009e7000);
  addword(&p, 0x500009e7); /* nop; nop; sbdone */

// Render control list
  p = list + 0xe200;

  // Clear color
  addbyte(&p, 114);
  addword(&p, 0xff000000); // Opaque Black
  addword(&p, 0xff000000); // 32 bit clear colours need to be repeated twice
  addword(&p, 0);
  addbyte(&p, 0);

  // Tile Rendering Mode Configuration
  addbyte(&p, 113);
  addword(&p, bus_addr + 0x10000); // framebuffer addresss
  addshort(&p, 1920); // width
  addshort(&p, 1080); // height
  addbyte(&p, 0x04); // framebuffer mode (linear rgba8888)
  addbyte(&p, 0x00);

  // Do a store of the first tile to force the tile buffer to be cleared
  // Tile Coordinates
  addbyte(&p, 115);
  addbyte(&p, 0);
  addbyte(&p, 0);
  // Store Tile Buffer General
  addbyte(&p, 28);
  addshort(&p, 0); // Store nothing (just clear)
  addword(&p, 0); // no address is needed

  // Link all binned lists together
  for(int x = 0; x < 30; x++) {
    for(int y = 0; y < 17; y++) {

      // Tile Coordinates
      addbyte(&p, 115);
      addbyte(&p, x);
      addbyte(&p, y);
      
      // Call Tile sublist
      addbyte(&p, 17);
      addword(&p, bus_addr + 0x6200 + (y * 30 + x) * 32);

      // Last tile needs a special store instruction
      if(x == 29 && y == 16) {
        // Store resolved tile color buffer and signal end of frame
        addbyte(&p, 25);
      } else {
        // Store resolved tile color buffer
        addbyte(&p, 24);
      }
    }
  }

  int render_length = p - (list + 0xe200);


// Run our control list
  printf("Binner control list constructed\n");
  printf("Start Address: 0x%08x, length: 0x%x\n", bus_addr, length);

  v3d[V3D_CT0CA] = bus_addr;
  v3d[V3D_CT0EA] = bus_addr + length;
  printf("V3D_CT0CS: 0x%08x, Address: 0x%08x\n", v3d[V3D_CT0CS], v3d[V3D_CT0CA]);

  // Wait for control list to execute
  while(v3d[V3D_CT0CS] & 0x20);
  
  printf("V3D_CT0CS: 0x%08x, Address: 0x%08x\n", v3d[V3D_CT0CS], v3d[V3D_CT0CA]);
  printf("V3D_CT1CS: 0x%08x, Address: 0x%08x\n", v3d[V3D_CT1CS], v3d[V3D_CT1CA]);


  v3d[V3D_CT1CA] = bus_addr + 0xe200;
  v3d[V3D_CT1EA] = bus_addr + 0xe200 + render_length;

  while(v3d[V3D_CT1CS] & 0x20);
  
  printf("V3D_CT1CS: 0x%08x, Address: 0x%08x\n", v3d[V3D_CT1CS], v3d[V3D_CT1CA]);
  v3d[V3D_CT1CS] = 0x20;

  // just dump the frame to a file
  FILE *f = fopen("frame.data", "w");
  fwrite(list + 0x10000, (1920*1080*4), 1, f);
  fclose(f);
  printf("frame buffer memory dumpped to frame.data\n");

// Release resources
  unmapmem((void *) list, 0x800000);
  mem_unlock(mbox, handle);
  mem_free(mbox, handle);
}
Exemple #15
0
int
main(int argc, char **argv)
{
	int fd;
	int ac;
	isdn_ioctl_struct ioctl_s;
	isdnloop_cdef newcard;
	isdnloop_sdef startparm;

	cmd = strrchr(argv[0], '/');
	cmd = (cmd == NULL) ? argv[0] : cmd + 1;
	if (argc > 1) {
		if (!strcmp(argv[1], "-d")) {
			strcpy(ioctl_s.drvid, argv[2]);
			arg_ofs = 3;
		} else {
			ioctl_s.drvid[0] = '\0';
			arg_ofs = 1;
		}
	} else
		usage();
	ac = argc - (arg_ofs - 1);
	fd = open("/dev/isdnctrl", O_RDWR);
	if (fd < 0) {
		perror(ctrldev);
		exit(-1);
	}
#ifdef __DEBUGVAR__
	if (!strcmp(argv[arg_ofs], "dump")) {
		char *p;
		ioctl_s.arg = (ulong) & dbg;
		if ((ioctl(fd, ISDNLOOP_IOCTL_DEBUGVAR + IIOCDRVCTL, &ioctl_s)) < 0) {
			perror("ioctl DEBUGVAR");
			exit(-1);
		}
		close(fd);
		p = mapmem(dbg.dev, sizeof(icn_dev));
		dump_dev((icn_dev *) p);
		p = mapmem(dbg.card, sizeof(icn_card));
		dump_card((icn_card *) p);
		return 0;
	}
#endif
	if (!strcmp(argv[arg_ofs], "leased")) {
		if (ac == 3) {
			ioctl_s.arg = 0;
			if ((!strcmp(argv[arg_ofs + 1], "on")) ||
			    (!strcmp(argv[arg_ofs + 1], "yes")))
				ioctl_s.arg = 1;
			if ((ioctl(fd, ISDNLOOP_IOCTL_LEASEDCFG + IIOCDRVCTL, &ioctl_s)) < 0) {
				perror("ioctl LEASEDCFG");
				exit(-1);
			}
			close(fd);
			return 0;
		}
	}
	if (!strcmp(argv[arg_ofs], "add")) {
		if (ac >= 2) {
			ioctl_s.arg = (unsigned long) &newcard;
			newcard.id1[0] = 0;
			strncpy(newcard.id1, argv[arg_ofs + 1], sizeof(newcard.id1) - 1);
			if ((ioctl(fd, ISDNLOOP_IOCTL_ADDCARD + IIOCDRVCTL, &ioctl_s)) < 0) {
				perror("ioctl ADDCARD");
				exit(-1);
			}
			close(fd);
			return 0;
		}
	}
	if (!strcmp(argv[arg_ofs], "start")) {
		int needed = 99;
		if (ac > 2) {
			if (!(strcmp(argv[arg_ofs + 1], "1tr6"))) {
				needed = 4;
				startparm.ptype = ISDN_PTYPE_1TR6;
			}
			if (!(strcmp(argv[arg_ofs + 1], "dss1"))) {
				needed = 6;
				startparm.ptype = ISDN_PTYPE_EURO;
			}
			if (ac >= needed) {
				strcpy(startparm.num[0], argv[arg_ofs + 2]);
				if (needed > 4) {
					strcpy(startparm.num[1], argv[arg_ofs + 3]);
					strcpy(startparm.num[2], argv[arg_ofs + 4]);
				}
				ioctl_s.arg = (unsigned long) &startparm;
				if (ioctl(fd, ISDNLOOP_IOCTL_STARTUP + IIOCDRVCTL, &ioctl_s) < 0) {
					perror("\nioctl STARTUP");
					exit(-1);
				}
				printf("done\n");
				close(fd);
				return 0;
			}
		}
		usage();
	}
	usage();
	return 0;
}
// Initialise this library.
int bcm2835_init(void)
{
    if (debug) 
    {
	bcm2835_pads = (uint32_t*)BCM2835_GPIO_PADS;
	bcm2835_clk  = (uint32_t*)BCM2835_CLOCK_BASE;
	bcm2835_gpio = (uint32_t*)BCM2835_GPIO_BASE;
	bcm2835_pwm  = (uint32_t*)BCM2835_GPIO_PWM;
	bcm2835_spi0 = (uint32_t*)BCM2835_SPI0_BASE;
	bcm2835_bsc0 = (uint32_t*)BCM2835_BSC0_BASE;
	bcm2835_bsc1 = (uint32_t*)BCM2835_BSC1_BASE;
	bcm2835_st   = (uint32_t*)BCM2835_ST_BASE;
	return 1; // Success
    }
    int memfd = -1;
    int ok = 0;
    // Open the master /dev/memory device
    if ((memfd = open("/dev/mem", O_RDWR | O_SYNC) ) < 0) 
    {
	fprintf(stderr, "bcm2835_init: Unable to open /dev/mem: %s\n",
		strerror(errno)) ;
	goto exit;
    }
	
    // GPIO:
    bcm2835_gpio = (volatile uint32_t *)mapmem("gpio", BCM2835_BLOCK_SIZE, memfd, BCM2835_GPIO_BASE);
    if (bcm2835_gpio == MAP_FAILED) goto exit;

    // PWM
    bcm2835_pwm = (volatile uint32_t *)mapmem("pwm", BCM2835_BLOCK_SIZE, memfd, BCM2835_GPIO_PWM);
    if (bcm2835_pwm == MAP_FAILED) goto exit;

    // Clock control (needed for PWM)
    bcm2835_clk = (volatile uint32_t *)mapmem("clk", BCM2835_BLOCK_SIZE, memfd, BCM2835_CLOCK_BASE);
    if (bcm2835_clk == MAP_FAILED) goto exit;
    
    bcm2835_pads = (volatile uint32_t *)mapmem("pads", BCM2835_BLOCK_SIZE, memfd, BCM2835_GPIO_PADS);
    if (bcm2835_pads == MAP_FAILED) goto exit;
    
    bcm2835_spi0 = (volatile uint32_t *)mapmem("spi0", BCM2835_BLOCK_SIZE, memfd, BCM2835_SPI0_BASE);
    if (bcm2835_spi0 == MAP_FAILED) goto exit;

    // I2C
    bcm2835_bsc0 = (volatile uint32_t *)mapmem("bsc0", BCM2835_BLOCK_SIZE, memfd, BCM2835_BSC0_BASE);
    if (bcm2835_bsc0 == MAP_FAILED) goto exit;

    bcm2835_bsc1 = (volatile uint32_t *)mapmem("bsc1", BCM2835_BLOCK_SIZE, memfd, BCM2835_BSC1_BASE);
    if (bcm2835_bsc1 == MAP_FAILED) goto exit;

    // ST
    bcm2835_st = (volatile uint32_t *)mapmem("st", BCM2835_BLOCK_SIZE, memfd, BCM2835_ST_BASE);
    if (bcm2835_st == MAP_FAILED) goto exit;

    ok = 1;

exit:
    if (memfd >= 0)
        close(memfd);

    if (!ok)
	bcm2835_close();

    return ok;
}
Exemple #17
0
int tx(uint32_t carrier_freq, char *audio_file, uint16_t pi, char *ps, char *rt, float ppm, char *control_pipe) {
    // Catch all signals possible - it is vital we kill the DMA engine
    // on process exit!
    for (int i = 0; i < 64; i++) {
        struct sigaction sa;

        memset(&sa, 0, sizeof(sa));
        sa.sa_handler = terminate;
        sigaction(i, &sa, NULL);
    }
        
    dma_reg = map_peripheral(DMA_VIRT_BASE, DMA_LEN);
    pwm_reg = map_peripheral(PWM_VIRT_BASE, PWM_LEN);
    clk_reg = map_peripheral(CLK_VIRT_BASE, CLK_LEN);
    gpio_reg = map_peripheral(GPIO_VIRT_BASE, GPIO_LEN);

    // Use the mailbox interface to the VC to ask for physical memory.
    mbox.handle = mbox_open();
    if (mbox.handle < 0)
        fatal("Failed to open mailbox. Check kernel support for vcio / BCM2708 mailbox.\n");
    printf("Allocating physical memory: size = %d     ", NUM_PAGES * 4096);
    if(! (mbox.mem_ref = mem_alloc(mbox.handle, NUM_PAGES * 4096, 4096, MEM_FLAG))) {
        fatal("Could not allocate memory.\n");
    }
    // TODO: How do we know that succeeded?
    printf("mem_ref = %u     ", mbox.mem_ref);
    if(! (mbox.bus_addr = mem_lock(mbox.handle, mbox.mem_ref))) {
        fatal("Could not lock memory.\n");
    }
    printf("bus_addr = %x     ", mbox.bus_addr);
    if(! (mbox.virt_addr = mapmem(BUS_TO_PHYS(mbox.bus_addr), NUM_PAGES * 4096))) {
        fatal("Could not map memory.\n");
    }
    printf("virt_addr = %p\n", mbox.virt_addr);
    

    // GPIO4 needs to be ALT FUNC 0 to output the clock
    gpio_reg[GPFSEL0] = (gpio_reg[GPFSEL0] & ~(7 << 12)) | (4 << 12);

    // Program GPCLK to use MASH setting 1, so fractional dividers work
    clk_reg[GPCLK_CNTL] = 0x5A << 24 | 6;
    udelay(100);
    clk_reg[GPCLK_CNTL] = 0x5A << 24 | 1 << 9 | 1 << 4 | 6;

    ctl = (struct control_data_s *) mbox.virt_addr;
    dma_cb_t *cbp = ctl->cb;
    uint32_t phys_sample_dst = CM_GP0DIV;
    uint32_t phys_pwm_fifo_addr = PWM_PHYS_BASE + 0x18;


    // Calculate the frequency control word
    // The fractional part is stored in the lower 12 bits
    uint32_t freq_ctl = ((float)(PLLFREQ / carrier_freq)) * ( 1 << 12 );


    for (int i = 0; i < NUM_SAMPLES; i++) {
        ctl->sample[i] = 0x5a << 24 | freq_ctl;    // Silence
        // Write a frequency sample
        cbp->info = BCM2708_DMA_NO_WIDE_BURSTS | BCM2708_DMA_WAIT_RESP;
        cbp->src = mem_virt_to_phys(ctl->sample + i);
        cbp->dst = phys_sample_dst;
        cbp->length = 4;
        cbp->stride = 0;
        cbp->next = mem_virt_to_phys(cbp + 1);
        cbp++;
        // Delay
        cbp->info = BCM2708_DMA_NO_WIDE_BURSTS | BCM2708_DMA_WAIT_RESP | BCM2708_DMA_D_DREQ | BCM2708_DMA_PER_MAP(5);
        cbp->src = mem_virt_to_phys(mbox.virt_addr);
        cbp->dst = phys_pwm_fifo_addr;
        cbp->length = 4;
        cbp->stride = 0;
        cbp->next = mem_virt_to_phys(cbp + 1);
        cbp++;
    }
    cbp--;
    cbp->next = mem_virt_to_phys(mbox.virt_addr);

    // Here we define the rate at which we want to update the GPCLK control 
    // register.
    //
    // Set the range to 2 bits. PLLD is at 500 MHz, therefore to get 228 kHz
    // we need a divisor of 500000 / 2 / 228 = 1096.491228
    //
    // This is 1096 + 2012*2^-12 theoretically
    //
    // However the fractional part may have to be adjusted to take the actual
    // frequency of your Pi's oscillator into account. For example on my Pi,
    // the fractional part should be 1916 instead of 2012 to get exactly 
    // 228 kHz. However RDS decoding is still okay even at 2012.
    //
    // So we use the 'ppm' parameter to compensate for the oscillator error

    float divider = (500000./(2*228*(1.+ppm/1.e6)));
    uint32_t idivider = (uint32_t) divider;
    uint32_t fdivider = (uint32_t) ((divider - idivider)*pow(2, 12));
    
    printf("ppm corr is %.4f, divider is %.4f (%d + %d*2^-12) [nominal 1096.4912].\n", 
                ppm, divider, idivider, fdivider);

    pwm_reg[PWM_CTL] = 0;
    udelay(10);
    clk_reg[PWMCLK_CNTL] = 0x5A000006;              // Source=PLLD and disable
    udelay(100);
    // theorically : 1096 + 2012*2^-12
    clk_reg[PWMCLK_DIV] = 0x5A000000 | (idivider<<12) | fdivider;
    udelay(100);
    clk_reg[PWMCLK_CNTL] = 0x5A000216;              // Source=PLLD and enable + MASH filter 1
    udelay(100);
    pwm_reg[PWM_RNG1] = 2;
    udelay(10);
    pwm_reg[PWM_DMAC] = PWMDMAC_ENAB | PWMDMAC_THRSHLD;
    udelay(10);
    pwm_reg[PWM_CTL] = PWMCTL_CLRF;
    udelay(10);
    pwm_reg[PWM_CTL] = PWMCTL_USEF1 | PWMCTL_PWEN1;
    udelay(10);
    

    // Initialise the DMA
    dma_reg[DMA_CS] = BCM2708_DMA_RESET;
    udelay(10);
    dma_reg[DMA_CS] = BCM2708_DMA_INT | BCM2708_DMA_END;
    dma_reg[DMA_CONBLK_AD] = mem_virt_to_phys(ctl->cb);
    dma_reg[DMA_DEBUG] = 7; // clear debug error flags
    dma_reg[DMA_CS] = 0x10880001;    // go, mid priority, wait for outstanding writes

    
    uint32_t last_cb = (uint32_t)ctl->cb;

    // Data structures for baseband data
    float data[DATA_SIZE];
    int data_len = 0;
    int data_index = 0;

    // Initialize the baseband generator
    if(fm_mpx_open(audio_file, DATA_SIZE) < 0) return 1;
    
    // Initialize the RDS modulator
    char myps[9] = {0};
    set_rds_pi(pi);
    set_rds_rt(rt);
    uint16_t count = 0;
    uint16_t count2 = 0;
    int varying_ps = 0;
    
    if(ps) {
        set_rds_ps(ps);
        printf("PI: %04X, PS: \"%s\".\n", pi, ps);
    } else {
        printf("PI: %04X, PS: <Varying>.\n", pi);
        varying_ps = 1;
    }
    printf("RT: \"%s\"\n", rt);
    
    // Initialize the control pipe reader
    if(control_pipe) {
        if(open_control_pipe(control_pipe) == 0) {
            printf("Reading control commands on %s.\n", control_pipe);
        } else {
            printf("Failed to open control pipe: %s.\n", control_pipe);
            control_pipe = NULL;
        }
    }
    
    
    printf("Starting to transmit on %3.1f MHz.\n", carrier_freq/1e6);

    for (;;) {
        // Default (varying) PS
        if(varying_ps) {
            if(count == 512) {
                snprintf(myps, 9, "%08d", count2);
                set_rds_ps(myps);
                count2++;
            }
            if(count == 1024) {
                set_rds_ps("RPi-Live");
                count = 0;
            }
            count++;
        }
        
        if(control_pipe && poll_control_pipe() == CONTROL_PIPE_PS_SET) {
            varying_ps = 0;
        }
        
        usleep(5000);

        uint32_t cur_cb = mem_phys_to_virt(dma_reg[DMA_CONBLK_AD]);
        int last_sample = (last_cb - (uint32_t)mbox.virt_addr) / (sizeof(dma_cb_t) * 2);
        int this_sample = (cur_cb - (uint32_t)mbox.virt_addr) / (sizeof(dma_cb_t) * 2);
        int free_slots = this_sample - last_sample;

        if (free_slots < 0)
            free_slots += NUM_SAMPLES;

        while (free_slots >= SUBSIZE) {
            // get more baseband samples if necessary
            if(data_len == 0) {
                if( fm_mpx_get_samples(data) < 0 ) {
                    terminate(0);
                }
                data_len = DATA_SIZE;
                data_index = 0;
            }
            
            float dval = data[data_index] * (DEVIATION / 10.);
            data_index++;
            data_len--;

            int intval = (int)((floor)(dval));
            //int frac = (int)((dval - (float)intval) * SUBSIZE);


            ctl->sample[last_sample++] = (0x5A << 24 | freq_ctl) + intval; //(frac > j ? intval + 1 : intval);
            if (last_sample == NUM_SAMPLES)
                last_sample = 0;

            free_slots -= SUBSIZE;
        }
        last_cb = (uint32_t)mbox.virt_addr + last_sample * sizeof(dma_cb_t) * 2;
    }

    return 0;
}