.. _hack_bbb_proj: BeagleBoneBlack, DLP2000 projector and FreeBSD ============================================== Under the cryptic name `DLPDLCR2000EVM `_ Texas Instruments sells a cute gadet, which turns the BeagleBoneBlack into a miniature projector: .. image:: dlpdlcr2000evm_dlp-lightcrafter-display-2000-board-image.JPG :scale: 50% To make it work with FreeBSD you will need a device tree overlay and a program to turn the project on via I2C. The overlay in source form:: /dts-v1/; / { part-number = "BB-LCD7-NH"; version = "00A7"; fragment@0 { target = <0xdeadbeef>; __overlay__ { pinmux_bb_lcd_lcd_pins { pinctrl-single,pins = <0xa0 0x8 0xa4 0x8 0xa8 0x8 0xac 0x8 0xb0 0x8 0xb4 0x8 0xb8 0x8 0xbc 0x8 0xc0 0x8 0xc4 0x8 0xc8 0x8 0xcc 0x8 0xd0 0x8 0xd4 0x8 0xd8 0x8 0xdc 0x8 0x3c 0x8 0x38 0x8 0x34 0x8 0x30 0x8 0x2c 0x8 0x28 0x8 0x24 0x8 0x20 0x8 0xe0 0x8 0xe4 0x8 0xe8 0x8 0xec 0x8 0x8c 0x17>; phandle = <0x1>; }; pinmux_bb_i2c2_pins { pinctrl-single,pins = <0x17c 0x73 0x178 0x73>; phandle = <0x2>; }; pinmux_edt_ft5x06_pins { pinctrl-single,pins = <0x1a4 0x27>; phandle = <0x3>; }; }; }; fragment@1 { target = <0xdeadbeef>; __overlay__ { status = "okay"; blue-and-red-wiring = "crossed"; }; }; fragment@2 { target = <0xdeadbeef>; __overlay__ { status = "okay"; pinctrl-names = "default"; pinctrl-0 = <0x2>; clock-frequency = <0x186a0>; #address-cells = <0x1>; #size-cells = <0x0>; edt-ft5x06@38 { status = "okay"; compatible = "edt,edt-ft5406", "edt,edt-ft5x06"; reg = <0x38>; pinctrl-names = "default"; pinctrl-0 = <0x3>; interrupt-parent = <0xdeadbeef>; interrupts = <0x13 0x0>; touchscreen-size-x = <0x320>; touchscreen-size-y = <0x1e0>; }; }; }; fragment@3 { target-path = "/"; __overlay__ { #address-cells = <0x1>; #size-cells = <0x1>; panel { status = "okay"; compatible = "ti,tilcdc,panel"; pinctrl-names = "default"; pinctrl-0 = <0x1>; panel-info { ac-bias = <0xff>; ac-bias-intrpt = <0x0>; dma-burst-sz = <0x10>; bpp = <0x20>; fdd = <0x80>; tft-alt-mode = <0x0>; stn-565-mode = <0x0>; mono-8bit-mode = <0x0>; sync-edge = <0x0>; sync-ctrl = <0x0>; raster-order = <0x0>; fifo-th = <0x0>; }; display-timings { native-mode = <0x4>; 640x360 { clock-frequency = <0x5a06e0>; hactive = <0x280>; vactive = <0x168>; hfront-porch = <0xe>; hback-porch = <0xc>; hsync-len = <0x4>; vback-porch = <0x9>; vfront-porch = <0x2>; vsync-len = <0x3>; hsync-active = <0x0>; vsync-active = <0x0>; pixelclk-active = <0x1>; phandle = <0x4>; }; }; }; }; }; __symbols__ { timing0 = "/fragment@3/__overlay__/panel/display-timings/640x360"; edt_ft5x06_pins = "/fragment@0/__overlay__/pinmux_edt_ft5x06_pins"; bb_i2c2_pins = "/fragment@0/__overlay__/pinmux_bb_i2c2_pins"; bb_lcd_lcd_pins = "/fragment@0/__overlay__/pinmux_bb_lcd_lcd_pins"; }; __fixups__ { am33xx_pinmux = "/fragment@0:target:0"; lcdc = "/fragment@1:target:0"; i2c2 = "/fragment@2:target:0"; gpio3 = "/fragment@2/__overlay__/edt-ft5x06@38:interrupt-parent:0"; }; __local_fixups__ { fragment@2 { __overlay__ { edt-ft5x06@38 { pinctrl-0 = <0x0>; }; }; }; fragment@2 { __overlay__ { pinctrl-0 = <0x0>; }; }; fragment@3 { __overlay__ { panel { display-timings { native-mode = <0x0>; }; }; }; }; fragment@3 { __overlay__ { panel { pinctrl-0 = <0x0>; }; }; }; }; }; And a small C-program for the I2C stuff:: #include #include #include #include #include #include #include #include static int write_bytes(int fd, int slave, int len, uint8_t *buf) { struct iic_msg msg[2]; struct iic_rdwr_data rdwr; msg[0].slave = slave << 1; msg[0].flags = IIC_M_WR; msg[0].len = len; msg[0].buf = buf; rdwr.msgs = msg; rdwr.nmsgs = 1; return (ioctl(fd, I2CRDWR, &rdwr)); } static int read_bytes(int fd, int slave, int off, int len, uint8_t *buf) { struct iic_msg msg[2]; struct iic_rdwr_data rdwr; uint8_t offset[2]; offset[0] = 0x15; offset[1] = off; msg[0].slave = slave << 1; msg[0].flags = IIC_M_WR; msg[0].len = sizeof( offset ); msg[0].buf = offset; msg[1].slave = slave << 1; msg[1].flags = IIC_M_RD; msg[1].len = len; msg[1].buf = buf; rdwr.msgs = msg; rdwr.nmsgs = 2; return (ioctl(fd, I2CRDWR, &rdwr)); } static int reset(int fd) { struct iiccmd ic; int i; memset(&ic, 0, sizeof ic); i = ioctl(fd, I2CRSTCARD, &ic); assert(i == 0); return (i); } static void rdall(int fd) { int i, j; uint8_t buf[16]; for (j = 0; j < 0x20; j++) { i = read_bytes(fd, 0x1b, j, 4, buf); printf("J %02x I %d %02x %02x %02x %02x\n", j, i, buf[0], buf[1], buf[2], buf[3]); } j = 0xb5; i = read_bytes(fd, 0x1b, j, 4, buf); printf("J %02x I %d %02x %02x %02x %02x\n", j, i, buf[0], buf[1], buf[2], buf[3]); } static void write_reg(int fd, int reg, unsigned val) { uint8_t buf[5]; int i; buf[0] = reg; be32enc(buf + 1, val); i = write_bytes(fd, 0x1b, 5, buf); printf("WRITE reg=0x%x val=0x%x i=%d [%02x %02x %02x %02x %02x]\n", reg, val, i, buf[0], buf[1], buf[2], buf[3], buf[4]); assert(i == 0); } int main(int argc, char **argv) { uint8_t buf[16]; int i, j; int fd = open("/dev/iic1", O_RDWR); assert(fd >= 0); write_reg(fd, 0xb, 0); write_reg(fd, 0xc, 0x1b); rdall(fd); return (0); return (0); } Compile the device tree overlay:: dtc -I dts -O dtb < the_dts_from_above > /boot/dtb/overlays/dtb.dtbo Compile the i2c code: cc -o /root/dlpiic the_c_source_from_above Add this line in `/boot/loader.conf`:: fdt_overlays="dlp.dtbo" Create `/etc/rc.d/dlp` with this content:: # BEFORE: disks /usr/sbin/gpioctl -f /dev/gpioc1 -v -c 16 OUT /usr/sbin/gpioctl -f /dev/gpioc1 -v 16 1 sleep .3 /root/dlpiic Remember to make it executable:: chmod +x /etc/rc.d/dlp and reboot the BBB... Install Xorg, start the X-server run "xfireworks" and turn of the light... *phk*