Mathematica-like environment on the mbed using USB keyboard input, VGA output, and a thermal printer.

Dependencies:   mbed Thermal 4DGL-uLCD-SE USBHost_Modified uVGAIII

main.cpp

Committer:
zrussell3
Date:
2018-12-13
Revision:
6:646d22295054
Parent:
4:b79d152dec32

File content as of revision 6:646d22295054:

#include "mbed.h"
#include "Thermal.h"
#include "uLCD_4DGL.h"
#include "USBHostKeyboard.h"
#include "uVGAIII.h"

extern "C" struct node* scanner(const char* es);
extern "C" float eval_expr(struct node* node, float x_value);

#include <math.h>

#define SIZE_X       480
#define SIZE_Y       800

// Debugging LEDs
DigitalOut led(LED1);
DigitalOut led2(LED2);
DigitalOut led3(LED3);
DigitalOut led4(LED4);

uVGAIII ecran(p9,p10,p11); // serial tx, serial rx, reset pin;
uLCD_4DGL uLCD(p13,p14,p12); // serial tx, serial rx, reset pin;
Thermal printer(p28, p27, 19200);

// Variables to track cursor location on VGA
int verticalCursor = 2;
int horizontalCursor = 0;

// Variables to hold user input & index
char currentLine[48];
int currentLineIndex = 0;

// Variables to track graph bitmaps
unsigned char bitmap[5000];
char temp[8];

// Mutexes for displays
Mutex VGA_Lock;
Mutex LCD_Lock;

char getPixel(int x, int y, int bk) {
    LCD_Lock.lock();
    int r = uLCD.read_pixel(x, y);
    LCD_Lock.unlock();
    
    if (r == bk) //same as background
        return '0';
    else
        return '1';
}

void makeBitmap() {
    LCD_Lock.lock();
    int bk = uLCD.read_pixel(127,127);
    LCD_Lock.unlock();
    for (int i = 0; i < 128*128/8; ++i) {
        for (int j = 0; j < 8; ++j) { //get next 8 bits and put them in temp array
            //temp[2*j] = getPixel((i%32)*4+j,i/32,bk);
            //temp[2*j+1] = temp[2*j];
            temp[j] = getPixel((i%16)*8+j,i/16,bk);
        }
       
        //need to convert to 0b format
        char * end;
        long int value = strtol(temp, &end, 2);
        //bitmap[64*(i/32)+(i%32)] = value;
        //bitmap[64*(i/32)+(i%32)+32] = value;
        bitmap[i] = value;
        led3 = !led3;
    }
    //printer.printf(bitmap);
    //printer.justify('C');
    printer.printBitmap(128,128,bitmap);
    printer.feed(2);
}


// hardcode plot x^2
void plotx2()
{
    LCD_Lock.lock();
    uLCD.cls();
    int xOffset = 0;
    int yOffset = 127;
    int pastX = 0;
    int pastY = 127;
    int currentX = 0;
    int currentY = 0;
    
    for(double i = 0; i < 11; i++) {
        //evaluate();
        currentX = i*10 + xOffset;
        currentY = yOffset-(i*i);
        if(pastX == 0){
            pastX = currentX;
            pastY = currentY;
            continue;
        }
        uLCD.line(pastX, pastY, currentX, currentY, RED);
        uLCD.line(pastX, pastY+1, currentX, currentY+1, RED);
        uLCD.line(pastX, pastY-1, currentX, currentY-1, RED);
        pastX = currentX;
        pastY = currentY;
    }
    LCD_Lock.unlock();
}

void plotsin()
{
    LCD_Lock.lock();
    uLCD.cls();
    int xOffset = 0;
    int yOffset = 64;
    int pastX = 0;
    int pastY = 64;
    int currentX = 0;
    int currentY = 0;
    
    for(double i = 0; i < 7; i+=.01) {
        //evaluate();
        currentX = i*16 + xOffset;
        currentY = yOffset-40*sin(i);
        if(pastX == 0){
            pastX = currentX;
            pastY = currentY;
            continue;
        }
        uLCD.line(pastX, pastY, currentX, currentY, RED);
        uLCD.line(pastX, pastY+1, currentX, currentY+1, RED);
        uLCD.line(pastX, pastY-1, currentX, currentY-1, RED);
        pastX = currentX;
        pastY = currentY;
    }
    LCD_Lock.unlock();
}


void plotx2vga(void const *)
{
    int xOffset = 600;
    int yOffset = 401;
    int pastX = 0;
    int pastY = 0;
    int currentX = 0;
    int currentY = 0;
    
    VGA_Lock.lock();
    
    for(double i = -20; i < 21; i++) {
        led4 = !led4;
        //evaluate(); // Where evaluate would go...if we could parse input        
        currentX = i*9 + xOffset;
        currentY = yOffset-(i*i);
        if(pastX == 0){
            pastX = currentX;
            pastY = currentY;
            continue;
        }
        ecran.line(pastX, pastY, currentX, currentY, RED);
        pastX = currentX;
        pastY = currentY;
    }
    
    VGA_Lock.unlock();
    
    while(1) {
        Thread::wait(500);
    }
    
}


void onKeyCode(uint8_t key, uint8_t modifier) {
    
    led3 = 1;
    
    // Skip spaces, empty spaces
    if(key == 0 || key == 0x20) {
        led3 = 0;
        return;
    }
    
    VGA_Lock.lock();
    
    // Handle newline
    if(key == 0x0A) {
        
        // Check if going off end of screen
        if(verticalCursor > 37) {
            ecran.filled_rectangle(0, 0 , 399, 480, DGREY);
            verticalCursor = 0;
        } else {
            // Move cursor to newline
            verticalCursor+=2;
        }
        
        horizontalCursor = 0;
        
        ecran.move_cursor(verticalCursor, horizontalCursor);
         
        ecran.puts(currentLine);  
        
        printer.printf(currentLine);
        printer.feed(2);
        
        struct node* expr = scanner(currentLine);
        float val = eval_expr(expr, 3.0);
        uLCD.printf("Evaluate: %f \n",val);
        
        for(size_t i = 0; i < 48; i++) {
            currentLine[i] = NULL;
        }
        
        currentLineIndex = 0;
        
        VGA_Lock.unlock();
        
        led3 = 0;
        return;
    }
    
    if(key == 0x08)
    {
        if(currentLineIndex != 0)
        {
            currentLineIndex--;
            currentLine[currentLineIndex] = NULL;
        }
        led3 = 0;
        
        VGA_Lock.unlock();
        
        return;
    }
    
    // Append character to curret line string
    currentLine[currentLineIndex] = (char)key;
    
    if(currentLineIndex < 47) {
        currentLineIndex++;
    }
    
    VGA_Lock.unlock();
    
    led3 = 0;
}

void keyboard_task(void const *) {
    
    USBHostKeyboard keyboard;
    
    while(1) {
        // try to connect a USB keyboard
        while(!keyboard.connect()) {
            Thread::wait(200);
        } 
        
        if(keyboard.connected()) led2 = 1;
        
        // When connected, attach handler called on keyboard event
        keyboard.attach(onKeyCode);
        
        // Wait until the keyboard is disconnected
        while(keyboard.connected())
            Thread::wait(500); 
            
        led2 = 0;
    }
}

int main() {  
    led = 1; 
    
    // Set up uLCD
    uLCD.baudrate(300000);
    uLCD.background_color(BLACK);
    
    // Set up VGA display
    ecran.baudrate(300000);
    ecran.screen_mode(LANDSCAPE);
    ecran.graphics_parameters(RESOLUTION, 2); 
    ecran.touch_status();
    ecran.background_color(DGREY);
    ecran.cls();

    ecran.move_cursor(0, 0);
    ecran.char_width('d');
    ecran.char_height('d');
    ecran.text_fgd_color(WHITE);
    ecran.text_bgd_color(DGREY);
    ecran.puts("Booting up...");   
    
    ecran.filled_rectangle(398,0,402,480,RED);
        
    // Use old style threading
    Thread keyboardTask(keyboard_task, NULL, osPriorityNormal, 256 * 4);   
    
    // Launch VGA plot through thread
    Thread vgaPlot(plotx2vga, NULL, osPriorityNormal, 256 * 4);

    plotx2();
    makeBitmap();
    led3 = 1;
    plotsin();
    makeBitmap();
    led3 = 1;
    
    // Clear currentLine array before using
    for(size_t i = 0; i < 48; i++) {
            currentLine[i] = NULL;
    }
    
    VGA_Lock.lock();
    ecran.move_cursor(2, 0);
    ecran.puts("Ready!");
    VGA_Lock.unlock();
    
    static const char es[] = "1 + 2 ^ 3 * 4 + 5 * x";
    struct node* expr = scanner(es);
    float val = eval_expr(expr, 3.0);
    
    while(1) {
        led=!led;
        Thread::wait(600); // Wait .6s in main thread
    }
}