Update firmware for lite version

This commit is contained in:
Wenting 2024-01-23 23:50:18 -05:00
parent b15cee3316
commit f50bc6edc6
9 changed files with 30331 additions and 30056 deletions

View file

@ -25,6 +25,7 @@ pico_sdk_init()
add_executable(fw
bitstream.c
caster.c
edid.c
fpga.c
fusb302.c

File diff suppressed because it is too large Load diff

87
fw/caster.c Normal file
View file

@ -0,0 +1,87 @@
//
// Glider
// Copyright 2024 Wenting Zhang
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <assert.h>
#include "config.h"
#include "caster.h"
#include "fpga.h"
static size_t last_update;
static size_t last_update_duration;
static uint8_t waveform_frames;
static uint8_t get_update_frames(void) {
// Should be worst case time to clear/ update a frame
//uint8_t min_time = 10; // Minimum time for non-LUT modes
// actually, just always return 1s
return 60;
}
static void wait(void) {
// Reading is not implemented in the simulator
}
void caster_init(void) {
waveform_frames = 38; // Need to sync with the RTL code
// fpga_write_reg8(CSR_CFG_V_FP, TCON_VFP);
// fpga_write_reg8(CSR_CFG_V_SYNC, TCON_VSYNC);
// fpga_write_reg8(CSR_CFG_V_BP, TCON_VBP);
// fpga_write_reg16(CSR_CFG_V_ACT, TCON_VACT);
// fpga_write_reg8(CSR_CFG_H_FP, TCON_HFP);
// fpga_write_reg8(CSR_CFG_H_SYNC, TCON_HSYNC);
// fpga_write_reg8(CSR_CFG_H_BP, TCON_HBP);
// fpga_write_reg16(CSR_CFG_H_ACT, TCON_HACT);
// fpga_write_reg8(CSR_CONTROL, 1); // Enable refresh
}
void caster_load_waveform(uint8_t *waveform, uint8_t frames) {
wait();
fpga_write_reg8(CSR_LUT_FRAME, 0); // Reset value before loading
fpga_write_reg16(CSR_LUT_ADDR, 0);
fpga_write_bulk(CSR_LUT_WR, waveform, WAVEFORM_SIZE);
waveform_frames = frames;
}
void caster_redraw(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1) {
wait();
fpga_write_reg16(CSR_OP_LEFT, x0);
fpga_write_reg16(CSR_OP_TOP, y0);
fpga_write_reg16(CSR_OP_RIGHT, x1);
fpga_write_reg16(CSR_OP_BOTTOM, y1);
fpga_write_reg8(CSR_OP_LENGTH, get_update_frames());
fpga_write_reg8(CSR_OP_CMD, OP_EXT_REDRAW);
}
void caster_setmode(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1,
UPDATE_MODE mode) {
wait();
fpga_write_reg16(CSR_OP_LEFT, x0);
fpga_write_reg16(CSR_OP_TOP, y0);
fpga_write_reg16(CSR_OP_RIGHT, x1);
fpga_write_reg16(CSR_OP_BOTTOM, y1);
fpga_write_reg8(CSR_OP_LENGTH, get_update_frames());
fpga_write_reg8(CSR_OP_PARAM, (uint8_t)mode);
fpga_write_reg8(CSR_OP_CMD, OP_EXT_SETMODE);
}

95
fw/caster.h Normal file
View file

@ -0,0 +1,95 @@
//
// Caster simulator
// Copyright 2023 Wenting Zhang
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
#pragma once
// Register map
#define CSR_LUT_FRAME 0
#define CSR_LUT_ADDR_HI 1
#define CSR_LUT_ADDR_LO 2
#define CSR_LUT_WR 3
#define CSR_OP_LEFT_HI 4
#define CSR_OP_LEFT_LO 5
#define CSR_OP_RIGHT_HI 6
#define CSR_OP_RIGHT_LO 7
#define CSR_OP_TOP_HI 8
#define CSR_OP_TOP_LO 9
#define CSR_OP_BOTTOM_HI 10
#define CSR_OP_BOTTOM_LO 11
#define CSR_OP_PARAM 12
#define CSR_OP_LENGTH 13
#define CSR_OP_CMD 14
#define CSR_CONTROL 15
#define CSR_CFG_V_FP 16
#define CSR_CFG_V_SYNC 17
#define CSR_CFG_V_BP 18
#define CSR_CFG_V_ACT_HI 19
#define CSR_CFG_V_ACT_LO 20
#define CSR_CFG_H_FP 21
#define CSR_CFG_H_SYNC 22
#define CSR_CFG_H_BP 23
#define CSR_CFG_H_ACT_HI 24
#define CSR_CFG_H_ACT_LO 25
#define CSR_CFG_FBYTES_B2 27
#define CSR_CFG_FBYTES_B1 28
#define CSR_CFG_FBYTES_B0 29
// Alias for 16bit registers
#define CSR_LUT_ADDR CSR_LUT_ADDR_HI
#define CSR_OP_LEFT CSR_OP_LEFT_HI
#define CSR_OP_RIGHT CSR_OP_RIGHT_HI
#define CSR_OP_TOP CSR_OP_TOP_HI
#define CSR_OP_BOTTOM CSR_OP_BOTTOM_HI
#define CSR_CFG_V_ACT CSR_CFG_V_ACT_HI
#define CSR_CFG_H_ACT CSR_CFG_H_ACT_HI
// Commands
#define OP_EXT_REDRAW 0
#define OP_EXT_SETMODE 1
// Status bits
#define STATUS_MIG_ERROR 7
#define STATUS_MIF_ERROR 6
#define STATUS_SYS_READY 5
#define STATUS_OP_BUSY 4
#define STATUS_OP_QUEUE 3
#define CTRL_ENABLE 0
#define WAVEFORM_SIZE (4*1024)
#define FRAME_RATE_HZ (60)
typedef enum {
UM_MANUAL_LUT_NO_DITHER = 0,
UM_MANUAL_LUT_ERROR_DIFFUSION = 1,
UM_FAST_MONO_NO_DITHER = 2,
UM_FAST_MONO_BAYER = 3,
UM_FAST_MONO_BLUE_NOISE = 4,
UM_FAST_GREY = 5,
UM_AUTO_LUT_NO_DITHER = 6,
UM_AUTO_LUT_ERROR_DIFFUSION = 7
} UPDATE_MODE;
void caster_init(void);
void caster_load_waveform(uint8_t *waveform, uint8_t frames);
void caster_redraw(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1);
void caster_setmode(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1,
UPDATE_MODE mode);

View file

@ -118,6 +118,15 @@
#define SCREEN_VBLK 29
#define SCREEN_VFP 3
#define SCREEN_VSYNC 10
#define TCON_HACT 256
#define TCON_HBP 2
#define TCON_HSYNC 2
#define TCON_HFP 72
#define TCON_VACT 758
#define TCON_VBP 3
#define TCON_VSYNC 1
#define TCON_VFP 12
#elif defined(SCREEN_1448_1072)
// 1448x1072 @ 60, 128.5MHz CVT
#define SCREEN_CLK 128500
@ -150,6 +159,15 @@
#define SCREEN_VBLK 35
#define SCREEN_VFP 21
#define SCREEN_VSYNC 8
#define TCON_HACT 400
#define TCON_HBP 2
#define TCON_HSYNC 2
#define TCON_HFP 16
#define TCON_VACT 1200
#define TCON_VBP 2
#define TCON_VSYNC 1
#define TCON_VFP 12
#elif defined(SCREEN_1872_1404)
// 1872x1404 @ 60, 162MHz Custom
#define SCREEN_CLK 162000

View file

@ -20,6 +20,8 @@
// SOFTWARE.
//
#include "pico/stdlib.h"
#include <stdio.h>
#include "utils.h"
#include "fpga.h"
#include "bitstream.h"
@ -58,22 +60,66 @@ static void fpga_send_byte(uint8_t byte) {
}
}
static void fpga_send_byte_slow(uint8_t byte) {
for (int i = 0; i < 8; i++) {
gpio_put(FPGA_MOSI, byte & 0x80);
delay_loop(20);
gpio_put(FPGA_SCLK, 1);
delay_loop(20);
byte <<= 1;
gpio_put(FPGA_SCLK, 0);
}
}
void fpga_write_reg8(uint8_t addr, uint8_t val) {
gpio_put(FPGA_CS, 0);
fpga_send_byte_slow(addr);
fpga_send_byte_slow(val);
gpio_put(FPGA_CS, 1);
}
void fpga_write_reg16(uint8_t addr, uint16_t val) {
gpio_put(FPGA_CS, 0);
fpga_send_byte_slow(addr);
fpga_send_byte_slow(val >> 8);
fpga_send_byte_slow(val & 0xff);
gpio_put(FPGA_CS, 1);
}
void fpga_write_bulk(uint8_t addr, uint8_t *buf, int length) {
gpio_put(FPGA_CS, 0);
fpga_send_byte_slow(addr);
for (int i = 0; i < length; i++) {
fpga_send_byte_slow(buf[i]);
}
gpio_put(FPGA_CS, 1);
}
static void fpga_load_bitstream(uint8_t *stream, int size) {
gpio_put(FPGA_CS, 0);
for (int i = 0; i < size; i++) {
fpga_send_byte(stream[i]);
}
gpio_put(FPGA_CS, 1);
for (int i = 0; i < 1000; i++) {
if (gpio_get(FPGA_DONE) == 1)
break;
sleep_ms(1);
}
if (gpio_get(FPGA_DONE) == 0) {
fatal("FPGA done does not go high after 1s");
printf("FPGA bitstream load done.\n");
}
static void fpga_wait_done(bool timeout) {
if (timeout) {
int i;
for (i = 0; i < 1000; i++) {
if (gpio_get(FPGA_DONE) == 1)
break;
sleep_ms(1);
}
if (gpio_get(FPGA_DONE) == 0) {
fatal("FPGA done does not go high after 1s");
}
printf("FPGA is up after %d ms.\n", i);
}
else {
printf("FPGA bitstream load done.");
while (gpio_get(FPGA_DONE) != 1);
printf("FPGA is up.\n");
}
}
@ -87,6 +133,8 @@ void fpga_init(void) {
gpio_init_ipu(FPGA_DONE);
gpio_init_out(FPGA_SUSP, 0);
gpio_put(FPGA_CS, 1);
// FPGA Reset
gpio_put(FPGA_PROG, 0);
sleep_ms(100);
@ -94,7 +142,14 @@ void fpga_init(void) {
sleep_ms(100);
// Load bitstream
#if 1
fpga_load_bitstream(fpga_bitstream, fpga_bitstream_length);
fpga_wait_done(true);
#else
fpga_wait_done(false);
#endif
}
void fpga_suspend(void) {

View file

@ -24,3 +24,6 @@
void fpga_init(void);
void fpga_suspend(void);
void fpga_resume(void);
void fpga_write_reg8(uint8_t addr, uint8_t val);
void fpga_write_reg16(uint8_t addr, uint16_t val);
void fpga_write_bulk(uint8_t addr, uint8_t *buf, int length);

45
fw/fw.c
View file

@ -32,6 +32,7 @@
#include "power.h"
#include "fpga.h"
#include "edid.h"
#include "caster.h"
int main()
{
@ -52,8 +53,52 @@ int main()
//sleep_goto_dormant_until_edge_high(8);
// https://ghubcoder.github.io/posts/awaking-the-pico/
fpga_init();
//sleep_ms(5000);
//caster_init();
gpio_init(2);
gpio_set_dir(2, GPIO_IN);
gpio_pull_up(2);
int mode_max = 6;
int mode = 1;
UPDATE_MODE modes[6] = {
UM_FAST_MONO_NO_DITHER,
UM_FAST_MONO_BAYER,
UM_FAST_MONO_BLUE_NOISE,
UM_FAST_GREY,
UM_AUTO_LUT_NO_DITHER,
UM_AUTO_LUT_ERROR_DIFFUSION
};
while (1) {
//
if (gpio_get(2) == 0) {
sleep_ms(20);
if (gpio_get(2) == 0) {
int i = 0;
while (gpio_get(2) == 0) {
i++;
sleep_ms(1);
if (i > 500)
break;
}
if (i > 500) {
// Long press, clear screen
caster_redraw(0,0,1600,1200);
}
else {
// Short press, switch mode
mode++;
if (mode >= mode_max) mode = 0;
caster_setmode(0,0,1600,1200,modes[mode]);
}
while (gpio_get(2) == 0);
}
while (gpio_get(2) == 0);
}
}
#elif defined(INPUT_TYPEC)
int result = tcpm_init(0);

View file

@ -25,8 +25,14 @@
#include "config.h"
#if defined(POWER_GPIO)
#define PWR_EN_GPIO 21
#define PWR_VCOM_GPIO 22
#define PWR_EN_GPIO 21
#define PWR_VCOM_GPIO 22
#if defined(POWER_GPIO_VCOM_MEASURE)
#define PWR_VCOM_EN_GPIO 28
#define PWR_VCOM_MEN_GPIO 26
#define PWR_VCOM_MEA_GPIO 27
#endif
void power_init(void) {
gpio_put(PWR_EN_GPIO, 0);
@ -37,6 +43,21 @@ void power_init(void) {
// Set period to 256 cycles
pwm_set_wrap(slice_num, 255);
pwm_set_gpio_level(PWR_VCOM_GPIO, 127);
// 0 -3.421V
// 127 -2.145V
// 255 -0.987V
#if defined(POWER_GPIO_VCOM_MEASURE)
gpio_init(PWR_VCOM_EN_GPIO);
gpio_put(PWR_VCOM_EN_GPIO, 0);
gpio_set_dir(PWR_VCOM_EN_GPIO, GPIO_OUT);
gpio_init(PWR_VCOM_MEN_GPIO);
gpio_put(PWR_VCOM_MEN_GPIO, 1);
gpio_set_dir(PWR_VCOM_MEN_GPIO, GPIO_OUT);
#endif
}
void power_enable(bool en) {