📄 alt_tpo_lcd.c
字号:
IOWR_ALTERA_AVALON_PIO_DATA(lcd->scl_pio, 0x0); usleep(1); IOWR_ALTERA_AVALON_PIO_DATA(lcd->scl_pio, 0x1); usleep(1); IOWR_ALTERA_AVALON_PIO_DATA(lcd->scl_pio, 0x0); usleep(1); /* Read in data byte */ for(i=0; i<8; i++) { /* Read & shift data */ read_data = read_data << 1; read_data |= (IORD_ALTERA_AVALON_PIO_DATA(lcd->sda_pio) & 0x01); /* Toggle clock & wait */ IOWR_ALTERA_AVALON_PIO_DATA(lcd->scl_pio, 0x1); usleep(1); IOWR_ALTERA_AVALON_PIO_DATA(lcd->scl_pio, 0x0); usleep(1); } return read_data;}/* * Function: alt_tpo_lcd_read_config_register * * Purpose: This routine reads a configuration word from the LCD * panel's serial interface port. * * The serial interface for LCD configuration is implemented with * three PIO peripherals, the base address of each is presumed to * be defined in the lcd configuration struct pointed to by *lcd. * * Timing information: * A 160-ns pulse width is required for scl; 150ns setup and hold * times for data transitions before/after the clock edge. Additionally, * a 1us-delay is required between successive commands (successive * calls to this routine). * * Because this routine is intended to be used only during initial setup, * latency isn't critical; the usleep() routine is used to generate a * predicable (if large) delay between each transition. This routine * may be immediatly called after it returns to write another register * in the LCD. * * Arguments: * *lcd: LCD configuration struct. This must be pre-populated with valid * base addresses of the LCD communication PIOs. * addr: byte containing 6-bit LCD configuration register address in LSBs * * Return value: * byte read from specified register address */alt_u8 alt_tpo_lcd_read_config_register(alt_tpo_lcd *lcd, alt_u8 addr){ alt_irq_context irq_state; alt_u8 read_data; alt_tpo_lcd_prepare_serial_bus(lcd); /* * Disable interrupts. The LCD requires a 40-60% duty cycle on the * serial clock signal, which we can only guarantee if this routine * runs uninterrupted. */ irq_state = alt_irq_disable_all(); /* Transmit 6-bit address */ alt_tpo_lcd_write_serial_bits(lcd, 6, addr); /* Do read */ read_data = alt_tpo_lcd_read_serial_byte(lcd); /* Done. Restore previously enabled interrupts & clean-up bus */ alt_irq_enable_all(irq_state); alt_tpo_lcd_cleanup_serial_bus(lcd); return read_data;}/* * Function: alt_tpo_lcd_write_config_register * * Purpose: This routine writes a configuration word to the LCD * panel's serial interface port. * * The serial interface for LCD configuration is implemented with * three PIO peripherals, the base address of each is presumed to * be defined in the lcd configuration struct pointed to by *lcd. * * Timing information: * A 160-ns pulse width is required for scl; 150ns setup and hold * times for data transitions before/after the clock edge. Additionally, * a 1us-delay is required between successive commands (successive * calls to this routine). * * Because this routine is intended to be used only during initial setup, * latency isn't critical; the usleep() routine is used to generate a * predicable (if large) delay between each transition. This routine * may be immediatly called after it returns to write another register * in the LCD. * * Arguments: * *lcd: LCD configuration struct. This must be pre-populated with valid * base addresses of the LCD communication PIOs * addr: byte containing 6-bit LCD configuration register address in LSBs * data: byte to write */void alt_tpo_lcd_write_config_register(alt_tpo_lcd *lcd, alt_u8 addr, alt_u8 data){ alt_irq_context irq_state; alt_tpo_lcd_prepare_serial_bus(lcd); /* * Disable interrupts. The LCD requires a 40-60% duty cycle on the * serial clock signal, which we can only guarantee if this routine * runs uninterrupted. */ irq_state = alt_irq_disable_all(); /* Transmit: * - 6-bit address * - "00" to indicate write, (this would be "1" then high-Z turnaround * cycle for a read) * - 8-bit data */ alt_tpo_lcd_write_serial_bits(lcd, 6, addr); alt_tpo_lcd_write_serial_bits(lcd, 2, (alt_u8) 0x0); alt_tpo_lcd_write_serial_bits(lcd, 8, data); /* Done. Restore previously enabled interrupts & clean-up bus */ alt_irq_enable_all(irq_state); alt_tpo_lcd_cleanup_serial_bus(lcd);}/******************************************************************* Function: alt_tpo_lcd_init** Purpose: This routine configures the LCD panel through its* serial interface port.*******************************************************************/int alt_tpo_lcd_init(alt_tpo_lcd *lcd, alt_u32 width, alt_u32 height){ alt_u8 data; /* Gamma curve */ unsigned short gamma[12] = { 106, 200, 289, 375, 460, 543, 625, 705, 785, 864, 942, 1020 }; /* Sanity check: Read Chip ID/Version */ data = alt_tpo_lcd_read_config_register(lcd, ALT_TPO_LCD_ADDR_CHIP_ID); /* Mask off "version" bits to only examine chip ID. Chip ID is high nibble */ data &= ALT_TPO_LCD_CHIP_ID_MASK; if(data != ALT_TPO_LCD_CHIP_ID) { printf("[alt_tpo_lcd_init] Warning: Read incorrect chip ID.\n"); printf("--> Expected 0x%x, read 0x%x\n", ALT_TPO_LCD_CHIP_ID, data); printf("--> The gamma curve or other LCD register writes may not succeed.\n"); } /* Enable software-writable resolution. */ data = alt_tpo_lcd_read_config_register(lcd, ALT_TPO_LCD_ADDR_RES_SEL_STBY); data |= 0x80; /* Bit 7 = Enable SW control for resolution */ alt_tpo_lcd_write_config_register(lcd, ALT_TPO_LCD_ADDR_RES_SEL_STBY, data); /* Set resolution */ if(width == 800 && height == 480) { alt_tpo_lcd_write_config_register( lcd, ALT_TPO_LCD_ADDR_RESOLUTION, (alt_u8) 0x7); } else if(width == 640 && height == 480) { alt_tpo_lcd_write_config_register( lcd, ALT_TPO_LCD_ADDR_RESOLUTION, (alt_u8) 0x6); } else if(width == 480 && height == 272) { alt_tpo_lcd_write_config_register( lcd, ALT_TPO_LCD_ADDR_RESOLUTION, (alt_u8) 0x5); } else { printf("[alt_tpo_lcd_init] Error: Width & height not supported.\n"); printf("--> This software supports 800x480, 640x480, or 480x272\n"); return -1; } /* * Write gamma curve * * Registers in the address range 0x11..0x13 contain the two MSBs of each * 10-bit gamma value. This is derived from manufacturer's datasheet. */ alt_tpo_lcd_write_config_register(lcd , 0x11, (alt_u8) ( ((gamma[0] & 0x300) >> 2) | ((gamma[1] & 0x300) >> 4) | ((gamma[2] & 0x300) >> 6) | ((gamma[3] & 0x300) >> 8 ) ) ); alt_tpo_lcd_write_config_register(lcd, 0x12, (alt_u8) ( ((gamma[4] & 0x300) >> 2) | ((gamma[5] & 0x300) >> 4) | ((gamma[6] & 0x300) >> 6) | ((gamma[7] & 0x300) >> 8 ) ) ); alt_tpo_lcd_write_config_register(lcd, 0x13, (alt_u8) ( ((gamma[8] & 0x300) >> 2) | ((gamma[9] & 0x300) >> 4) | ((gamma[10] & 0x300) >> 6) | ((gamma[11] & 0x300) >> 8 ) ) ); /* * Register addresses 0x14..0x1f contain 8-bit gamma values. */ alt_tpo_lcd_write_config_register(lcd, 0x14, (alt_u8)( gamma[0] & 0xFF ) ); alt_tpo_lcd_write_config_register(lcd, 0x15, (alt_u8)( gamma[1] & 0xFF ) ); alt_tpo_lcd_write_config_register(lcd, 0x16, (alt_u8)( gamma[2] & 0xFF ) ); alt_tpo_lcd_write_config_register(lcd, 0x17, (alt_u8)( gamma[3] & 0xFF ) ); alt_tpo_lcd_write_config_register(lcd, 0x18, (alt_u8)( gamma[4] & 0xFF ) ); alt_tpo_lcd_write_config_register(lcd, 0x19, (alt_u8)( gamma[5] & 0xFF ) ); alt_tpo_lcd_write_config_register(lcd, 0x1a, (alt_u8)( gamma[6] & 0xFF ) ); alt_tpo_lcd_write_config_register(lcd, 0x1b, (alt_u8)( gamma[7] & 0xFF ) ); alt_tpo_lcd_write_config_register(lcd, 0x1c, (alt_u8)( gamma[8] & 0xFF ) ); alt_tpo_lcd_write_config_register(lcd, 0x1d, (alt_u8)( gamma[9] & 0xFF ) ); alt_tpo_lcd_write_config_register(lcd, 0x1e, (alt_u8)( gamma[10] & 0xFF ) ); alt_tpo_lcd_write_config_register(lcd, 0x1f, (alt_u8)( gamma[11] & 0xFF ) ); /* * Register address 0x20 controls the "voltage range for * positive polarity" (and negative polarity, for 0x21). * High nibble defines DAC reference voltage for "code 0xFF" * Low nibble defines DAC reference voltage for "code 0x00" */ alt_tpo_lcd_write_config_register(lcd, 0x20, (alt_u8) 0xF0); alt_tpo_lcd_write_config_register(lcd, 0x21, (alt_u8) 0xF0); return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -