Revert "Un-DMA LCD code"

This reverts commit 6ca974487f.
This commit is contained in:
jaseg 2023-05-03 14:10:53 +02:00
parent 6ca974487f
commit 23be368b68

View file

@ -284,13 +284,14 @@ static void led_init() {
static void i2c_init(void);
static void lcd_init(void);
static void lcd_pex_set_noblock(uint8_t value);
static void i2c_write(uint8_t addr, size_t n);
static void i2c_nonblocking_mode(void);
static void i2c_blocking_mode(void);
static void lcd_tx_nibble(uint8_t value, uint8_t flags);
static void lcd_pex_set(uint8_t value);
static void lcd_poll(void);
static void delay_us(int duration_us);
static void lcd_command(uint8_t value);
static void lcd_write(const char **buf);
static void lcd_write_dma(const char **buf);
/* https://www.lcd-module.de/eng/pdf/zubehoer/ks0066.pdf */
@ -342,9 +343,8 @@ enum LCD_FUNCTION_Cmd {
struct {
uint8_t buf[512];
size_t bpos;
size_t ndt;
bool run;
uint32_t cr2_buf;
bool blocking;
} st_i2c;
bool lcd_led;
@ -353,12 +353,31 @@ void i2c_init() {
memset(&st_i2c, 0, sizeof(st_i2c));
SYSCFG->CFGR1 |= SYSCFG_CFGR1_I2C1_DMA_RMP | SYSCFG_CFGR1_TIM17_DMA_RMP2;
/* Magic value for 100kHz I2C @ 48MHz CLK. Fell out of STMCubeMX, then tweaked looking at an oscilloscope. I love
* downloading 120MB of software to download another 100MB of software, only this time over unsecured HTTP, to
* generate 3.5 bytes of configuration values using a Java(TM) GUI. */
/* Magic value for 100kHz I2C @ 48MHz CLK. Fell out of STMCubeMX. I love downloading 120MB of software to download
* another 100MB of software, only this time over unsecured HTTP, to generate 3.5 bytes of configuration values
* using a Java(TM) GUI. */
I2C1->TIMINGR = (0<<I2C_TIMINGR_PRESC_Pos) | (11<<I2C_TIMINGR_SCLDEL_Pos) | (0<<I2C_TIMINGR_SDADEL_Pos) |
(51<<I2C_TIMINGR_SCLH_Pos) | (46<<I2C_TIMINGR_SCLL_Pos);
I2C1->CR1 = I2C_CR1_PE;
I2C1->CR1 = I2C_CR1_ERRIE | I2C_CR1_TXDMAEN | I2C_CR1_PE;
/* TIM1 for DMA timing */
TIM17->PSC = 47;
TIM17->ARR = 50;
TIM17->DIER = TIM_DIER_UDE;
TIM17->CR1 = TIM_CR1_CEN;
/* I2C1 TX */
DMA1_Channel6->CCR = (0<<DMA_CCR_MSIZE_Pos) | (0<<DMA_CCR_PSIZE_Pos) | DMA_CCR_MINC | DMA_CCR_DIR | DMA_CCR_TEIE | DMA_CCR_TCIE;
DMA1_Channel6->CPAR = (uint32_t)&(I2C1->TXDR);
DMA1_Channel6->CMAR = (uint32_t)&st_i2c.buf;
/* I2C1 START trigger */
DMA1_Channel7->CCR = (2<<DMA_CCR_MSIZE_Pos) | (2<<DMA_CCR_PSIZE_Pos) | DMA_CCR_DIR | DMA_CCR_TEIE;
DMA1_Channel7->CPAR = (uint32_t)&(I2C1->CR2);
DMA1_Channel7->CMAR = (uint32_t)&st_i2c.cr2_buf;
NVIC_EnableIRQ(DMA1_Channel4_5_6_7_IRQn);
NVIC_EnableIRQ(I2C1_IRQn);
}
/*
@ -379,17 +398,13 @@ enum I2C1_Address {
LCD_PEX_ADDR = 0x4E,
};
void lcd_pex_set_noblock(uint8_t value) {
void lcd_pex_set(uint8_t value) {
if (lcd_led) {
value |= B_LCD_LED;
}
I2C1->TXDR = value;
I2C1->CR2 = (1 << I2C_CR2_NBYTES_Pos) | I2C_CR2_AUTOEND | (LCD_PEX_ADDR << I2C_CR2_SADD_Pos) | I2C_CR2_START;
}
void lcd_pex_set(uint8_t value) {
lcd_pex_set_noblock(value);
while (I2C1->ISR & I2C_ISR_BUSY || !(I2C1->ISR & I2C_ISR_TXE)) {
/* do nothing. */
}
@ -414,29 +429,18 @@ void lcd_command(uint8_t value) {
lcd_tx_nibble(value, 0);
}
void lcd_poll() {
if (!st_i2c.run) {
return;
void lcd_write_dma(const char **buf) {
DMA1_Channel6->CCR &= ~DMA_CCR_EN;
DMA1_Channel7->CCR &= ~DMA_CCR_EN;
while ((DMA1_Channel6->CCR & DMA_CCR_EN) | (DMA1_Channel7->CCR & DMA_CCR_EN)) {
/* do nothing */
}
if (!(I2C1->ISR & I2C_ISR_BUSY) && (12C1->ISR & I2C_ISR_TXE)) {
I2C1->TXDR = st_i2c.txd[st_i2c.bpos];
I2C1->CR2 = (1 << I2C_CR2_NBYTES_Pos) | I2C_CR2_AUTOEND | (LCD_PEX_ADDR << I2C_CR2_SADD_Pos) | I2C_CR2_START;
st_i2c.bpos++;
if (st_i2c.bpos == st_i2c.ndt) {
st_i2c.run = false;
st_i2c.bpos = 0;
}
}
}
void lcd_write(const char **buf) {
uint8_t line_offset[4] = {0, 64, 20, 84};
uint8_t led = lcd_led ? B_LCD_LED : 0;
uint8_t *p = st_i2c.buf;
for (size_t line=0; line<4; line++) {
uint8_t command = LCD_CMD_DDRAM_ADDR | line_offset[line];
/* set address */
*p++ = ((command>>4)<<4) | B_LCD_E | led;
@ -458,13 +462,20 @@ void lcd_write(const char **buf) {
*p++ = led;
*p++ = led;
st_i2c.ndt = p - st_i2c.buf;
st_i2c.bpos = 0;
st_i2c.run = true;
size_t n = p - st_i2c.buf;
DMA1_Channel6->CNDTR = n;
DMA1_Channel6->CCR |= DMA_CCR_TCIE;
DMA1_Channel6->CCR |= DMA_CCR_EN;
st_i2c.cr2_buf = (1 << I2C_CR2_NBYTES_Pos) | I2C_CR2_AUTOEND | (LCD_PEX_ADDR << I2C_CR2_SADD_Pos) | I2C_CR2_START;
DMA1_Channel7->CNDTR = n;
DMA1_Channel7->CCR |= DMA_CCR_EN;
}
void lcd_init() {
lcd_led = false;
i2c_init();
i2c_blocking_mode();
delay_us(40000);
lcd_tx_nibble(LCD_ENTER_4BIT, 0);
@ -473,6 +484,47 @@ void lcd_init() {
lcd_command(LCD_CMD_CLEAR);
delay_us(2000);
lcd_command(LCD_CMD_ENTRY_MODE | LCD_ENTRY_CUR_RIGHT);
lcd_led = true;
i2c_nonblocking_mode();
}
void i2c_write(uint8_t addr, size_t n) {
DMA1_Channel6->CCR &= ~DMA_CCR_EN;
while (DMA1_Channel6->CCR & DMA_CCR_EN) {
/* do nothing */
}
DMA1_Channel6->CNDTR = n;
DMA1_Channel6->CCR |= DMA_CCR_EN;
I2C1->CR2 = (n << I2C_CR2_NBYTES_Pos) | I2C_CR2_AUTOEND | (addr << I2C_CR2_SADD_Pos);
I2C1->CR2 |= I2C_CR2_START;
if (st_i2c.blocking) {
while ((!(DMA1->ISR & DMA_ISR_TCIF6)) || (I2C1->ISR & I2C_ISR_BUSY)) {
/* do nothing */
}
}
}
void i2c_nonblocking_mode() {
DMA1_Channel6->CCR &= ~DMA_CCR_EN;
while (DMA1_Channel6->CCR & DMA_CCR_EN) {
/* do nothing */
}
DMA1_Channel6->CCR |= DMA_CCR_TCIE;
st_i2c.blocking = false;
}
void i2c_blocking_mode() {
DMA1_Channel6->CCR &= ~DMA_CCR_EN;
while (DMA1_Channel6->CCR & DMA_CCR_EN) {
/* do nothing */
}
DMA1_Channel6->CCR &= ~DMA_CCR_TCIE;
st_i2c.blocking = true;
}
void DMA1_Channel4_5_6_7_IRQHandler() {
@ -486,6 +538,16 @@ void DMA1_Channel4_5_6_7_IRQHandler() {
}
}
void I2C1_IRQHandler() {
int flags = I2C1->ISR;
if (flags & (I2C_ISR_ARLO | I2C_ISR_BERR)) {
I2C1->ICR = I2C_ISR_ARLO | I2C_ISR_BERR;
asm volatile ("bkpt");
}
}
#define USB_EP0_SIZE 8
#define USB_CDC_RX_EP 0x01
#define USB_CDC_TX_EP 0x81
@ -864,7 +926,7 @@ int main(void) {
"LINE 2 LINE 2 LINE 2",
"LINE 3 LINE 3 LINE 3",
"LINE 4 LINE 4 LINE 4"};
lcd_write(lines);
lcd_write_dma(lines);
led_init();
usbd_init(&usb_dev, &usbd_hw, USB_EP0_SIZE, usb_buf, sizeof(usb_buf));
@ -903,7 +965,7 @@ int main(void) {
st_led.led[i].b += 3;
}
for (size_t i=0; i<100000; i++) {
lcd_poll();
asm volatile ("nop");
}
}
}