Skip to content

Commit 235984e

Browse files
added LCD section
1 parent 5e306d8 commit 235984e

File tree

1 file changed

+109
-10
lines changed

1 file changed

+109
-10
lines changed

gowin_empu/README.md

Lines changed: 109 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -244,7 +244,9 @@ Gowin also provides a CMSIS Peripheral Access Layer System in the "CMSIS\system\
244244
- The "gw1ns4c.h" header file which defines the register structs of the various peripherals and the memory addresses at which the peripherals can be found. Gowin suggests that the user only imports this specific header in their "main.c" file.
245245
- The "system_gw1ns4c.c" file which is primarily used for clock configuration, it defines global system/peripheral clock variables, and functions for initializing and updating them. The SystemCoreClock variable in particular is part of CMSIS-Core and various peripherals may rely on its value for their operation so it's important that it matches the real-life clocking situation (the clock signal at the EMPU's clock pin). SystemCoreClockUpdate() simply copies the predefined __SYSTEM_CLOCK macro by default, but it can be modified to update SystemCoreClock in order to match frequency changes from the PLL (PLLVR can change output clock division dynamically to obtain a slower clock for power-saving purposes).
246246

247-
Finally, GMD requires a linker script that defines the size of available SRAM and flash, and the placement of various code sections. A sample linker script is provided by Gowin as "Script/flash/gmd/gw1ns4c_flash.ld".
247+
GMD requires a linker script that defines the size of available SRAM and flash, and the placement of various code sections. A sample linker script is provided by Gowin as "Script/flash/gmd/gw1ns4c_flash.ld".
248+
249+
Finally, the StdPeriph_Driver folder contains libraries for the various peripherals including UART, GPIO, timers etc... To use a peripheral you should consult the comments in its driver library source file.
248250

249251
### **Clock and SRAM configuration**
250252

@@ -389,15 +391,15 @@ Each C file gets a listing inside the Debug directory, for example the "main.c"
389391
//Initializes UART0
390392
void initializeUART()
391393
{
392-
UART_InitTypeDef uartInitStruct;
393-
//Enable transmission
394-
uartInitStruct.UART_Mode.UARTMode_Tx = ENABLE;
395-
//Disable reception
396-
uartInitStruct.UART_Mode.UARTMode_Rx = DISABLE;
397-
//9600 baud rate typical of Arduinos
398-
uartInitStruct.UART_BaudRate = 9600;
399-
//Initialize UART0 using the struct configs
400-
UART_Init(UART0, &uartInitStruct);
394+
UART_InitTypeDef uartInitStruct;
395+
//Enable transmission
396+
uartInitStruct.UART_Mode.UARTMode_Tx = ENABLE;
397+
//Disable reception
398+
uartInitStruct.UART_Mode.UARTMode_Rx = DISABLE;
399+
//9600 baud rate typical of Arduinos
400+
uartInitStruct.UART_BaudRate = 9600;
401+
//Initialize UART0 using the struct configs
402+
UART_Init(UART0, &uartInitStruct);
401403
}
402404

403405
void initializeTimer() {
@@ -455,6 +457,103 @@ Each C file gets a listing inside the Debug directory, for example the "main.c"
455457

456458
* If the retargeting doesn't work for whatever reason, try using UART_SendString(UART0, char*) instead. You can use snprintf() to format a string in advance before sending it.
457459
### **1602 Character LCD library**
460+
You can interface the EMPU itself with a Hitachi HD44780-based (or compatible) character LCD by using a simple library I made a while back, it works by bit-banging LCD commands through the GPIOs and functions in 4-bit data bus mode for now.
461+
* [Download the LCD library repository](https://github.com/verilog-indeed/nano_4k_1602_lcd), extract and copy the LCD_LIBRARY folder to your GMD project's folder.
462+
* Refresh the project explorer then go to the project's properties and head to "C/C++ Build -> Settings -> GNU ARM Cross C Compiler -> Includes", add the "LCD_LIBRARY/Includes" directory to the include paths.
463+
* Try this LCD example: (replace contents of main.c)
464+
```
465+
/* Includes ------------------------------------------------------------------*/
466+
#include "gw1ns4c.h"
467+
#include <stdio.h>
468+
#include <string.h>
469+
#include "lcd_hd44780.h"
470+
/*----------------------------------------------------------------------------*/
471+
472+
/* Declarations*/
473+
void initializeTimer();
474+
void delayMillis(uint32_t ms);
475+
char messageBuffer[16];
476+
//bitmap of the "yaz" character
477+
int amazighGlyph[8] = {0b10101,
478+
0b10101,
479+
0b11111,
480+
0b00100,
481+
0b00100,
482+
0b11111,
483+
0b10101,
484+
0b10101};
485+
486+
int main(void)
487+
{
488+
SystemInit(); //Configures CPU for the defined system clock
489+
initializeTimer();
490+
//Initializes GPIO used by LCD and LCD itself
491+
LCD_Init();
492+
493+
//Create the Tifinagh "yaz" character at index 0
494+
LCD_CreateCustomChar(0, amazighGlyph);
495+
496+
//Cursor to beginning of second line
497+
LCD_LineSelect(1);
498+
//Write custom character at index 0
499+
//You can also put alphanumeric ASCII characters
500+
LCD_WriteChar(0);
501+
502+
uint32_t counter = 0;
503+
while(1)
504+
{
505+
//Cursor to beginning of first line
506+
LCD_LineSelect(0);
507+
//format string and store in buffer
508+
snprintf(messageBuffer, 16, "/r/GowinFPGA! #%d", counter);
509+
LCD_WriteString(messageBuffer);
510+
511+
delayMillis(2000);
512+
counter++;
513+
}
514+
}
515+
516+
void initializeTimer() {
517+
TIMER_InitTypeDef timerInitStruct;
518+
519+
timerInitStruct.Reload = 0;
520+
521+
//Disable interrupt requests from timer for now
522+
timerInitStruct.TIMER_Int = DISABLE;
523+
524+
//Disable timer enabling/clocking from external pins (GPIO)
525+
timerInitStruct.TIMER_Exti = TIMER_DISABLE;
526+
527+
TIMER_Init(TIMER0, &timerInitStruct);
528+
TIMER_StopTimer(TIMER0);
529+
}
530+
531+
#define CYCLES_PER_MILLISEC (SystemCoreClock / 1000)
532+
void delayMillis(uint32_t ms) {
533+
TIMER_StopTimer(TIMER0);
534+
//Reset timer just in case it was modified elsewhere
535+
TIMER_SetValue(TIMER0, 0);
536+
TIMER_EnableIRQ(TIMER0);
537+
538+
uint32_t reloadVal = CYCLES_PER_MILLISEC * ms;
539+
//Timer interrupt will trigger when it reaches the reload value
540+
541+
TIMER_SetReload(TIMER0, reloadVal);
542+
TIMER_StartTimer(TIMER0);
543+
//Block execution until timer wastes the calculated amount of cycles
544+
while (TIMER_GetIRQStatus(TIMER0) != SET);
545+
546+
TIMER_StopTimer(TIMER0);
547+
TIMER_ClearIRQ(TIMER0);
548+
TIMER_SetValue(TIMER0, 0);
549+
}
550+
```
551+
* Connect a 16x2 LCD (16-pin module) to the board:
552+
* Disconnect the Nano 4K. Connect power and ground of the LCD's controller and backlight, and connect the output of a potentiometer to V0 for contrast setting. You can power it on and make sure the contrast adjustment works.
553+
* Connect pins 32, 31, 30, 29, 28 and 27 of the Nano 4K to the pins E, RS, D4, D5, D6 and D7 of the LCD respectively.
554+
* Tie the RW pin on the LCD to ground.
555+
* Build the project, connect the Nano 4K and flash the updated files. You should see a message on the LCD:
556+
(TODO picture)
458557

459558

460559
## **Conclusion**:

0 commit comments

Comments
 (0)