Touchscreen digit recognition.

Dependencies:   mbed TFT_fonts SPI_TFT_ILI9341 Adafruit_GFX FT6206 MMA8451Q

main.cpp

Committer:
atomicle
Date:
2020-01-17
Revision:
2:1ab6ba7c2c90
Parent:
1:c44001c6bbf8

File content as of revision 2:1ab6ba7c2c90:

#include <algorithm>
#include <string>

// Vendor
#include "mbed.h"
#include "SPI_TFT_ILI9341.h"
#include "FT6206.h"
#include "MMA8451Q.h"
#include "Arial12x12.h"
#include "Arial24x23.h"
#include "Arial28x28.h"

#include "weigths.hpp"
#include "orientation.hpp"

// Accelorameter
#if   defined (TARGET_KL25Z) || defined (TARGET_KL46Z)
  PinName const SDA = PTE25;
  PinName const SCL = PTE24;
#elif defined (TARGET_KL05Z)
  PinName const SDA = PTB4;
  PinName const SCL = PTB3;
#elif defined (TARGET_K20D50M)
  PinName const SDA = PTB1;
  PinName const SCL = PTB0;
#else
  #error TARGET NOT DEFINED
#endif

#define MMA8451_I2C_ADDRESS (0x1d<<1)

// Pin Configuration
#define PIN_XP          A3
#define PIN_XM          A1
#define PIN_YP          A2
#define PIN_YM          A0
#define PIN_SCLK        D13
#define PIN_MISO        D12
#define PIN_MOSI        D11
#define PIN_CS_TFT      D10
#define PIN_DC_TFT      D9
#define PIN_RESET_TFT   D8
#define PIN_CS_SD       D4


#define PIN_SCL_FT6206  A5
#define PIN_SDA_FT6206  A4
#define PIN_INT_FT6206  D7

#define ILI9341_TFTWIDTH  320
#define ILI9341_TFTHEIGHT 240

DigitalOut led1(LED1);
DigitalOut led2(LED2);
DigitalOut led3(LED3);
DigitalOut led4(LED4);

Ticker ticker;

SPI_TFT_ILI9341 TFT(PIN_MOSI, PIN_MISO, PIN_SCLK, PIN_CS_TFT, PIN_RESET_TFT, PIN_DC_TFT, "TFT");
FT6206 FT6206(PIN_SDA_FT6206, PIN_SCL_FT6206, PIN_INT_FT6206);
MMA8451Q acc(SDA, SCL, MMA8451_I2C_ADDRESS);

int maxIndex(float vector_name[])
{
    double max = vector_name[0];
    int index = 0;
    for (int i = 0; i != 10; i++) {
        if (max < vector_name[i]) {
            max = vector_name[i];
            index = i;
        }
    }
    return index;
}

float RELU(float x)
{
    return std::max(0.0f, x);
}

int FeedForward()
{
    float convImages[kernel_count][convImageSize][convImageSize] = {0.0f};

    for (unsigned f = 0; f != kernel_count; f++) {
        for (unsigned i = 0; i <= image_size - kernel_size; i += stride) {
            for (unsigned j = 0; j <= image_size - kernel_size; j += stride) {
                for (unsigned k = i; k < i + kernel_size; k++) {
                    for (unsigned l = j; l < j + kernel_size; l++) {
                        convImages[f][i / stride][j / stride] += image[k][l] * kernels[f][k - i][l - j];
                    }
                }
                convImages[f][i / stride][j / stride] += bias_kernels[f];
            }
        }
    }    

    unsigned elem = 0;
    for (unsigned f = 0; f != kernel_count; f++) {
        for (unsigned j = 0; j != convImageSize; j++) {
            for (unsigned k = 0; k != convImageSize; k++) {
                activated[elem++] = RELU(convImages[f][j][k]);
            }
        }
    }

    float z[10] = {0.0f};
    for (unsigned i = 0; i != 10; i++) {
        z[i] = 0.0f;
        for (unsigned j = 0; j != kernel_count * convImageSize * convImageSize; j++) {
            z[i] += weights[i][j] * activated[j];
        }
        z[i] += bias_weights[i];
    }
    return maxIndex(z);
}


void landscapeInit()
{
    //Configure the display driver
    TFT.claim(stdout);
    TFT.background(LightGrey);
    TFT.foreground(Green);
    TFT.set_orientation(LANDSCAPE);
    TFT.cls();

    //Print a welcome message
    TFT.fillrect(240, 25, 292, 45, Red);
    TFT.set_font((unsigned char*) Arial12x12);
    TFT.locate(245, 30);
    TFT.background(Red);
    TFT.printf("Guess");

    //Print a welcome message
    TFT.fillrect(240, 205, 292, 225, Red);
    TFT.set_font((unsigned char*) Arial12x12);
    TFT.locate(245, 210);
    TFT.background(Red);
    TFT.printf("Clear");

    TFT.fillrect(20, 50, 160, 190, DarkGrey);
}

void portraitInit()
{
    //Configure the display driver
    TFT.claim(stdout);
    TFT.background(LightGrey);
    TFT.foreground(Green);
    TFT.set_orientation(PORTRAIT);
    TFT.cls();

    //Print a welcome message
    TFT.fillrect(15, 25, 67, 45, Red);
    TFT.set_font((unsigned char*) Arial12x12);
    TFT.locate(20, 30);
    TFT.background(Red);
    TFT.printf("Guess");

    //Print a welcome message
    TFT.fillrect(160, 25, 212, 45, Red);
    TFT.set_font((unsigned char*) Arial12x12);
    TFT.locate(170, 30);
    TFT.background(Red);
    TFT.printf("Clear");

    TFT.fillrect(50, 160, 190, 300, DarkGrey);
}

int current_orientation = LANDSCAPE;

void set_orientation()
{
    current_orientation = get_orientation();
}
    
int main(void)
{
        
    int orientation = get_orientation();
    ticker.attach(&set_orientation, 0.1);

    if (orientation == LANDSCAPE)
        landscapeInit();
    else
        portraitInit();
    
    
    // Initialize weights
    for (unsigned i = 0; i != 28; i++)
    {
        for (unsigned j = 0; j != 28; j++)
        {
            image[i][j] = -0.5f;
        }
    }



    FT6206.begin();
    while(1)
    {   
        if (current_orientation != orientation)
        {
            orientation = current_orientation;
            if (orientation == LANDSCAPE)
                landscapeInit();
            else
                portraitInit();
        }
            
        if (FT6206.dataReceived())
        {
            TS_Point p = FT6206.getPoint();
            
            if (orientation == LANDSCAPE) {
                if (p.x >= 25 and p.x <= 155 and p.y >= 55 and p.y <= 185)
                {
                    // Handwriting panel has been pressed
                    TFT.fillcircle(p.x, p.y, 4, Yellow);
                    int image_y = (p.x-20)/5;
                    int image_x = (p.y-50)/5;
                    if (image_x > 0 and image_y > 0)
                    {
                        image[image_x-1][image_y-1] = 0.5f;
                        image[image_x-1][image_y] = 0.5f;
                        image[image_x-1][image_y+1] = 0.5f;
                        image[image_x][image_y-1] = 0.5f;
                        image[image_x][image_y] = 0.5f;
                        image[image_x][image_y+1] = 0.5f;
                        image[image_x+1][image_y-1] = 0.5f;
                        image[image_x+1][image_y] = 0.5f;
                        image[image_x+1][image_y+1] = 0.5f;
                    }
                } 
                else if (p.y >= 0 and p.y <= 60 and p.x >= 200 and p.x <= 320)
                {
                    // Guess button has been pressed
                    TFT.fillrect(180, 50, 320, 190, LightGrey);
                    TFT.locate(270, 110);
                    TFT.background(LightGrey);
                    TFT.foreground(Green);
                    
                    TFT.set_font((unsigned char*) Arial28x28);
                    switch (FeedForward())
                    {
                        case 0: TFT.printf("0"); break;
                        case 1: TFT.printf("1"); break;
                        case 2: TFT.printf("2"); break;
                        case 3: TFT.printf("3"); break;
                        case 4: TFT.printf("4"); break;
                        case 5: TFT.printf("5"); break;
                        case 6: TFT.printf("6"); break;
                        case 7: TFT.printf("7"); break;
                        case 8: TFT.printf("8"); break;
                        case 9: TFT.printf("9"); break;
                        default: TFT.printf("noidea\n");
                    }
                } 
                else if (p.y >= 185 and p.y <= 240 and p.x >= 220 and p.x <= 320)
                {
                    // Clear button has been pressed
                    TFT.fillrect(15, 45, 165, 195, LightGrey);
                    TFT.fillrect(20, 50, 160, 190, DarkGrey);
                    for (unsigned i = 0; i != 28; i++)
                    {
                        for (unsigned j = 0; j != 28; j++)
                        {
                            image[i][j] = -0.5f;
                        }
                    }
                } // LANDSCAPE END
            }
            else // PORTRAIT START
            {
                if (p.x >= 160 and p.x <= 300 and p.y >= 50 and p.y <= 190)
                {
                    // Handwriting panel has been pressed
                    TFT.fillcircle(240-p.y, p.x, 4, Yellow);
                    int image_x = (p.x-160)/5;
                    int image_y = (240- p.y-50)/5;
                    if (image_x > 0 and image_y > 0)
                    {
                        image[image_x-1][image_y-1] = 0.5f;
                        image[image_x-1][image_y] = 0.5f;
                        image[image_x-1][image_y+1] = 0.5f;
                        image[image_x][image_y-1] = 0.5f;
                        image[image_x][image_y] = 0.5f;
                        image[image_x][image_y+1] = 0.5f;
                        image[image_x+1][image_y-1] = 0.5f;
                        image[image_x+1][image_y] = 0.5f;
                        image[image_x+1][image_y+1] = 0.5f;
                    }
                } 
                else if (p.y >= 140 and p.y <= 240 and p.x >= 1 and p.x <= 70)
                {
                    // Guess button has been pressed
                    TFT.fillrect(90, 0, 140, 60, LightGrey);
                    char prediction = FeedForward();
                    TFT.locate(110, 30);
                    TFT.background(LightGrey);
                    TFT.foreground(Green);
                    
                    TFT.set_font((unsigned char*) Arial28x28);
                    switch (prediction)
                    {
                        case 0: TFT.printf("0"); break;
                        case 1: TFT.printf("1"); break;
                        case 2: TFT.printf("2"); break;
                        case 3: TFT.printf("3"); break;
                        case 4: TFT.printf("4"); break;
                        case 5: TFT.printf("5"); break;
                        case 6: TFT.printf("6"); break;
                        case 7: TFT.printf("7"); break;
                        case 8: TFT.printf("8"); break;
                        case 9: TFT.printf("9"); break;
                        default: TFT.printf("noidea\n");
                    }
                } 
                else if (p.y >= 1 and p.y <= 80 and p.x >= 0 and p.x <= 70)
                {
                    // Clear button has been pressed
                    TFT.fillrect(45, 155, 195, 305, LightGrey);
                    TFT.fillrect(50, 160, 190, 300, DarkGrey);
                    for (unsigned i = 0; i != 28; i++)
                    {
                        for (unsigned j = 0; j != 28; j++)
                        {
                            image[i][j] = -0.5f;
                        }
                    }
                }
            }
        }
    }
}