st7735s: documentation, ready for merge
[cortex-from-scratch] / drivers / st7735s.c
index 8eef4f3..a3c7117 100644 (file)
@@ -5,8 +5,19 @@
  * Initial version 
  * 
  * $DESCRIPTION$
+ * Basic driver for the ST7735s TFT screen. Initializes the screen 
+ * Low-level commands can be called by tft_command. See header (.h)
+ * file for an overview of all commands. tft_command can accepts
+ * an unlimited amount of data or parameter commands.
  * 
  * $USAGE$
+ * I added the following functionality:
+ * a. tft_fill: fills a certain area of the screen
+ * b. tft_setpixel: sets a single pixel
+ * c. tft_putc, tft_put: outputs a char/string to the screen, starts
+ * at the upper top right and tracks the position. If the screen is
+ * full, it 'scrolls' automatically. So you basically have a mini 
+ * sized terminal. You can link standard output to this function!
  *
  * */
 
 #include <lib/regfunc.h>
 #include <lib/string.h>
 #include <lib/tinyprintf.h>
-//#include <lib/fonts/wogfont.h>
+#include <lib/fonts/wogfont.h>
 
+#include <drivers/uart.h>
 #include <drivers/st7735s.h>
 
 #define TIMEOUT 500
 #define SCRWIDTH 132
 #define SCRHEIGHT 132
+#define STARTX 5
+#define STARTY 5
+#define XPOS(x) (x * 6)
+#define YPOS(y) (y * 8)
+#define BUFFER 352
+
+
+static struct {
+        uint16_t cpos;
+        uint8_t * textmemptr;
+                uint8_t buf[BUFFER];
+         uint8_t x;
+                uint8_t y;
+} tftscreen;
 
-int tft_putc(uint16_t, uint16_t, char);
 void tft_init() {
 
+       tftscreen.x = 0;
+       tftscreen.y = 0;
+       tftscreen.cpos = 0;
+       tftscreen.textmemptr = tftscreen.buf;
+
+       memset(tftscreen.buf, 0x00, 352); 
+
        /* Peripherial init */
        rsetbit(RCC_APB1ENR, 14); // enable SPI2
        rsetbit(RCC_APB2ENR, 3); // enable GPIOB
@@ -97,32 +129,13 @@ void tft_init() {
        /* Before turning on the display, fill the display
         * so no random display data is shown */
        tft_fill(0,0,SCRWIDTH-1,SCRHEIGHT-1,0x0000);
-       //tft_setpixel(50,50,0xFFFF);
-       tft_putc(0xFFFF, 0x0000, 's');
-       
+
        /* Turn on */
        tft_command(TFT_NORON, 0);
        _block(10000);
        tft_command(TFT_DISPON, 0);
        _block(100000);
-
-
-       /* //_block(10000); 
-
-       tft_command(TFT_CASET, 4, 0x00, 0x08, 0x00, 0x09);
-       tft_command(TFT_RASET, 4, 0x00, 0x08, 0x00, 0x09);
-       tft_command(TFT_RAMRD, 0);
-
-       //tft_command(0x0C, 0);
-       //tft_command(0x0A, 0);
        
-       rclrbit(SPI2_CR1, 14); // receive
-
-        while(!rchkbit(SPI2_SR, 0));
-        uint8_t chip_id = *SPI2_DR;
-        printf("COLMOD: %#x\n", chip_id); */
-
-       rclrbit(SPI2_CR1, 8); // deselect
 }
 
 /* Helper function */
@@ -186,27 +199,91 @@ tft_command(TFT_RAMWR, 2, (uint8_t) (color >> 8), (uint8_t) (color & 0xFF));
        return 0;
 }
 
-/* Low-level function to print a character to the display
- * Should not be used directly, since it does not set
- * the location */
-int tft_putc(uint16_t fg, uint16_t bg, char c) {
-
-       //chipselect();
-       // Bitmaps are 9 by 8
-       uint8_t databuf[9] =  {0x73, 0xFB, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0xDF, 0xDA};
-       //uint8_t databuf[9] =  {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
+
+/* Basic puts function that loops over a string */
+int tft_puts(char * str) {
+
+       for (int i = 0; i < strlen(str); i++)  {
+               tft_putc(0xFFFF, 0x0000, str[i]);
+
+       }
        
-       int totalpixels = 72;
-       int column, row = 0;
+}
+
+/* Used by scroll function to overwrite and clear the last
+ * line on the screen */
+void tft_clrln() {
+
+       tft_puts("                     ");
+       tftscreen.buf[BUFFER - 21] = '\0';
+       tftscreen.cpos -= 21;
+       tftscreen.y = 14;
+}
+
+/* Text scroll function 
+ * Refeed the buffer */
+int tft_scroll() {
+
+       /* Scroll the buffer  */
+       memcpy(tftscreen.textmemptr, tftscreen.textmemptr + 21, BUFFER - 21);
+       tftscreen.buf[BUFFER - 21] = '\0';
+
+       tftscreen.x = 0;
+       tftscreen.y = 0;
+       tftscreen.cpos = 0;
+
+       tft_puts(tftscreen.buf); // CHECK: ending
+       tftscreen.y = 14;
+       tftscreen.x = 0;
+       tftscreen.cpos = BUFFER - 21;
+}
+
+/* Fills a line with blank characters, returns to 
+ * the next line */
+void tft_nl() {
+
+       uint8_t blanks = 21 - tftscreen.x;
+
+       // filler with blank spaces
+       for (int i = 0; i < blanks; i++) {
+               tft_putc(0xFFFF, 0x0000, ' ');
+       }
+       
+}
+
+/* Low-level function to print a character to the display
+ * Should not be used directly */
+int tft_putc(uint16_t fg, uint16_t bg, int c) {
+
+       int totalpixels = 35;
+       int column = 0;
+       int row = 0;
        uint8_t current;
 
-       tft_command(TFT_CASET, 4, 0x00, 10, 0x00, 18);
-       tft_command(TFT_RASET, 4, 0x00, 10, 0x00, 17);
+       if (c == '\n') {
+               if (tftscreen.y == 14) {
+                       tft_nl();
+                       return 1;
+               }
+               else {
+                       tft_nl();
+               //if (tftscreen.y < 15)
+                       return 1;
+               }
+       }
+
+       if (tftscreen.y >= 15) {
+               tft_scroll();
+       }
+
+       tft_command(TFT_CASET, 4, 0x00, STARTX + XPOS(tftscreen.x), 0x00, (STARTX + 4) + XPOS(tftscreen.x));
+       tft_command(TFT_RASET, 4, 0x00, STARTY + YPOS(tftscreen.y), 0x00, (STARTY + 6) + YPOS(tftscreen.y));
+       
        tft_command(TFT_RAMWR, 0);
        rsetbit(GPIOC_ODR, 6); // data = 1      
        for (int i = 0; i < totalpixels; i++) {
                
-               current = databuf[column];
+               current = ASCII5x7[(c * 5) + column]; 
 
                if ((current >> (7 - row)) & 0x1) {
                        rwrite(SPI2_DR, (uint8_t) (fg >> 8));
@@ -227,16 +304,25 @@ int tft_putc(uint16_t fg, uint16_t bg, char c) {
 
                /* Algoritm dependent on draw mode: top down, left right */
                column++;
-               if (column > 8) {
+               if (column > 4) {
                        column = 0;
                        row++;  
                }
        }
+       tftscreen.buf[tftscreen.cpos] = c;
+       tftscreen.cpos++;
+
+       tftscreen.x++;
+       if (tftscreen.x > 20) {
+               tftscreen.x = 0;
+               tftscreen.y++;
+       }
+
        return 0;
-       // lookup table
 }
 
 
+
 /* Invokes commands with a variable list of paramaters. Sending parameters
  * requires the D/CX line to be high  */
 int tft_command(uint8_t cmd, int argsc, ...) {