POUR NUCLEO-F302R8

Dependencies:   X_NUCLEO_6180XA1 mbed

Fork of 247-436-M1-S2-LAB-A by Yves Roy

main.cpp

Committer:
YROY2004
Date:
2018-02-07
Revision:
4:8c64f7896cbf
Parent:
3:b115775ee641

File content as of revision 4:8c64f7896cbf:

#include "mbed.h"
#include "XNucleo6180XA1.h"
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>

//BRANCHEMENTS:
// Ni le Nucleo ni le vl6180x n'ont de "pullup" pour supporter le I2C.
// Il faut ajouter des résistances de 4.7k
// Le vl6180x contient un microcontôleur qui doit être remis à zéro au démarrage
// Cette remise à zéro se fait en mettant temporairement la broche gpio à la masse.
// Un schéma de connexion sommaire suit:
//    __________
//   | VL6180X  |                    
//   |          |
//   scl sda  gnd
//   nc  gpio 3.3v
//   |__________|

//   _______________________
//  |                       |
//  |    NUCLEO f302r8      |
//  | oo                 oo | 
//  | oo             scl-oo |
//  | oo             sda-oo |
//  | oo                 oo |
//  | oo             gnd-oo |
//  | oo                 oo |
//  | oo            gpio-oo |
//  | oo-3.3V            oo |
//             ...
//  | oo                 oo |
//  | cn7              cn10 | 
//  |_______________________|

// connexions:
// vl6180x.3.3v <------> nucleo.3.3V
// Vl6180x.scl <--------> nucleo.scl <-----> 4.7k <------> 3.3v  (pullup requise)
// Vl6180x.sda <--------> nucleo.sda <-----> 4.7k <------> 3.3v  (pullup requise)
// VL6180X.gpio <-------> nucleo.gpio (requis pour faire un "reset" du vl6180x au début)


//options de compilation
//#define TEST

//intégration
// représentation
// G: gauche, D: droit, H: haut, B: bas
// E: écran, T: touch
// Ecran:
//  (XE_G,YE_H)  ___  (XE_D,YE_H)
//              |   |
//              |   |
//  (XE_G,YE_B) |___| (XE_G,YE_B)
//
// représentation du touch
//  (XT_G,YT_H)  ___  (XT_D,YT_H)
//              |   |
//              |   |
//  (XT_G,YT_B) |___| (XT_G,YT_B)

// équations pour conversion
// XT: x touch lu, YT: y touch lu, XE: x ecran, YE: y ecran
// XE = (XE_D - XE_G)/(XT_D - XT_G)*(XT - XT_G) + XE_G
// YE = (YE_H - YE_B)/(YT_H - YT_B)*(YT - YT_G) + YE_G

// l'application présente 3 boutons et une surface de dessin
// bouton noir: effacer
// bouton rouge: dessiner en rouge
// bouton blanc: dessiner en blanc

//touchscreen
#define IDLE    1
#define ACTIVE  0
#define COMMAND 0
#define DATA    1

#define YP A3
#define XM A2 
#define YM D9  
#define XP D8 

#define TOUCH_SEUIL_HAUT    3000
#define TOUCH_SEUIL_BAS     16


#define TFTWIDTH  240
#define TFTHEIGHT 320

#define LCD_CS A3
#define LCD_CD A2
#define LCD_WR A1
#define LCD_RD A0
#define LCD_RESET A4

#define TFT_NORTH SPFD5408_MADCTL_MY | SPFD5408_MADCTL_BGR

#define BLACK   0x0000
#define BLUE    0x001F
#define RED     0xF800
#define GREEN   0x07E0
#define CYAN    0x07FF
#define MAGENTA 0xF81F
#define YELLOW  0xFFE0
#define WHITE   0xFFFF

#define SPFD5408_SOFTRESET          0x01
#define SPFD5408_SLEEPOUT           0x11

#define SPFD5408_DISPLAYON          0x29
#define SPFD5408_COLADDRSET         0x2A
#define SPFD5408_PAGEADDRSET        0x2B
#define SPFD5408_MEMORYWRITE        0x2C
#define SPFD5408_PIXELFORMAT        0x3A
#define SPFD5408_FRAMECONTROL       0xB1
#define SPFD5408_MEMCONTROL         0x36
#define SPFD5408_MADCTL_MY          0x80
#define SPFD5408_MADCTL_BGR         0x08

#define IDLE    1
#define ACTIVE  0
#define COMMAND 0
#define DATA    1

#define TEMPS   40

//VL6180X
#define VL6180X_I2C_SDA   D14 
#define VL6180X_I2C_SCL   D15 

#define VL6180X_I2C_SDA_MODE    PullUp
#define VL6180X_I2C_SCL_MODE    PullUp


//integration

#define XE_G    0
#define XE_D    240
#define YE_H    0
#define YE_B    320
#define XT_G    3700
#define XT_D    600
#define YT_H    600
#define YT_B    3700

#define MODE_COULEUR_CONSTANTE  0
#define MODE_COULEUR_VARIABLE   1
//definitions de variables
//touchscreen
uint16_t x;
uint16_t y;
uint16_t z;

//tftspfd5408
DigitalOut pinRD(LCD_RD);       //PA_0;
DigitalOut pinWR(LCD_WR);       //PA_1;
DigitalOut pinCD(LCD_CD);       //PA_4;
DigitalOut pinCS(LCD_CS);       //PB_0;
DigitalOut pinReset(LCD_RESET); //PC_1;

//VL6180X
DigitalOut enableVL6180X(D12);
static XNucleo6180XA1 *board = NULL;
uint32_t dist;

//integration
#ifdef TEST
    Serial pc(USBTX, USBRX, 9600); //SERIAL_TX, SERIAL_RX, 9600);
#endif

DigitalOut myled(LED1);
uint16_t couleurVariable;
uint16_t tableDeCouleur[]=
    {
       BLACK, RED, YELLOW, GREEN, CYAN, BLUE, MAGENTA, WHITE
    };   


//declarations de fonctions
//touchscreen 
void restoreXY(void);
uint16_t readTouchX(void);
uint16_t readTouchY(void);
uint16_t detectTouch(void);

//tftspfd5408
void WriteCommand(uint8_t c);
void WriteData(uint8_t d);
void begin(void);
void setAddrWindow(int x1, int y1, int x2, int y2);
void fillRect(uint16_t x1, uint16_t y1, uint16_t w, uint16_t h, uint16_t fillcolor);

//definitions de fonctions
//touchscreen
void restoreXY(void)
{
DigitalOut pinXP(XP);
DigitalOut pinXM(XM);    
DigitalOut pinYP(YP);
DigitalOut pinYM(YM);

    pinXP = 1;
    pinXM = 1;
    pinYP = 1;
    pinYM = 1;
    wait_ms(1);
}

uint16_t readTouchX(void)
{
uint16_t value;
DigitalOut pinXP(XP); 
DigitalOut pinXM(XM);
AnalogIn pinYP(YP);
DigitalIn pinYM(YM);

    pinXP = 0;
    pinXM = 1;
    pinYM.mode(OpenDrain);
    value = pinYP.read_u16() >> 4;
    restoreXY();
    return value;
}

uint16_t readTouchY(void)
{
uint16_t value;
DigitalIn pinXP(XP); 
AnalogIn pinXM(XM);
DigitalOut pinYP(YP);
DigitalOut pinYM(YM);

    pinYP = 1;
    pinYM = 0;
    pinXP.mode(OpenDrain);
    value = pinXM.read_u16() >> 4;
    restoreXY();    
    return value;
}

uint16_t detectTouch(void)
{
uint16_t firstValue;
uint16_t secondValue;
DigitalOut pinXP(XP); 
DigitalOut pinXM(XM);
AnalogIn pinYP(YP);
DigitalIn pinYM(YM);
    
    pinYM.mode(OpenDrain);
    pinXP = 1;
    pinXM = 0;
    firstValue = pinYP.read_u16() >> 4;

    pinXP = 0;
    pinXM = 1;
    secondValue = pinYP.read_u16() >> 4;

    restoreXY();
    
    if (secondValue > firstValue)
    {
        return firstValue;
    }
    return secondValue;
}

//tftspfd5408
void WriteCommand(uint8_t c)
{
BusInOut portTFT(D8, D9, D2, D3, D4, D5, D6, D7);
    portTFT.output();    
    pinCD = COMMAND;
    pinWR = ACTIVE;
    portTFT = c;
    pinWR = IDLE;
}

void WriteData(uint8_t d)
{
BusInOut portTFT(D8, D9, D2, D3, D4, D5, D6, D7);
    portTFT.output();    
    pinCD = DATA;
    pinWR = ACTIVE;
    portTFT = d;
    pinWR = IDLE;
}

void begin(void)
{
    pinCS = IDLE; 
    pinCD = DATA;
    pinWR = IDLE;
    pinRD = IDLE;

    pinReset = ACTIVE;
    wait_ms(100);
    pinReset = IDLE;
    wait_ms(100);
    pinCS = ACTIVE;
    
    WriteCommand(SPFD5408_SOFTRESET);
    WriteData(0);
    wait_ms(50);
    
    WriteCommand(SPFD5408_MEMCONTROL);
    WriteData(TFT_NORTH); //(SPFD5408_MADCTL_MY | SPFD5408_MADCTL_BGR);
    
    WriteCommand(SPFD5408_PIXELFORMAT);
    WriteData(0x55);
  
    WriteCommand(SPFD5408_FRAMECONTROL);
    WriteData(0x00);
    WriteData(0x1B);
  
    WriteCommand(SPFD5408_SLEEPOUT);
    WriteData(0);
  
    WriteCommand(SPFD5408_DISPLAYON);
    WriteData(0);
}

void setAddrWindow(int x1, int y1, int x2, int y2) {
    pinCS = ACTIVE;
    wait_us(TEMPS);
    WriteCommand(SPFD5408_COLADDRSET);
    WriteData(x1 >> 8);
    WriteData(x1);
    WriteData(x2 >> 8);
    WriteData(x2);
    wait_us(TEMPS);
    pinCS = IDLE;

    pinCS = ACTIVE;
    wait_us(TEMPS);
    WriteCommand(SPFD5408_PAGEADDRSET);
    WriteData(y1 >> 8);
    WriteData(y1);
    WriteData(y2 >> 8);
    WriteData(y2);
    pinCS = IDLE;
}

void fillRect(uint16_t x1, uint16_t y1, uint16_t w, uint16_t h, uint16_t fillcolor)
{
    BusInOut portTFT(D8, D9, D2, D3, D4, D5, D6, D7);
    uint8_t hi, lo;
    uint16_t  x2, y2;
    uint16_t i, j;

    portTFT.output();    

    x2 = x1 + w - 1;
    y2 = y1 + h - 1;
    setAddrWindow(x1, y1, x2, y2);

    hi = fillcolor >> 8;
    lo = fillcolor;

    pinCS = ACTIVE;

    WriteCommand(SPFD5408_MEMORYWRITE);
    pinCD = DATA;
    for (i = h; i > 0; i--)
    {
        for (j = w; j > 0; j--)

        {
            pinWR = ACTIVE;
            portTFT = hi;
            pinWR = IDLE; 
            pinWR = ACTIVE;
            portTFT = lo;
            pinWR = IDLE;             
        }
    }
    pinCS = IDLE;
}
 
//intégration

int32_t conversion(int32_t x, int32_t x0, int32_t y0, int32_t x1, int32_t y1)
{
    int32_t retour;
    int32_t limiteInferieure;
    int32_t limiteSuperieure;
    if (y0 < y1)
    {
        limiteInferieure = y0;
        limiteSuperieure = y1;
    }
    else
    {
        limiteInferieure = y1;
        limiteSuperieure = y0;
    }
    retour = (x - x0) * (y1 -y0) / (x1 -x0) + y0;
  
    if (retour < limiteInferieure)
    {
        return limiteInferieure;
    }        
    if (retour > limiteSuperieure)
    {
        return limiteSuperieure;
    }
    return retour;
};

uint16_t determineLaCouleur(void)
{

    board->sensor_top->get_distance(&dist);
    if (dist > 210) //en millimetres
    {
        dist = 210;
    }
//    board->sensor_top->get_lux(&lux);
        
        return tableDeCouleur[(int)(dist/30)];
}

int main()
{
//variables locales du touchscreen 
uint16_t couleur;

//variables locales du tftspfd5408

//variables locales pour le VL6180X
int status;
uint32_t lux;

DevI2C *device_i2c = new DevI2C(VL6180X_I2C_SDA, VL6180X_I2C_SCL);


//variables locales pour l'integration
uint32_t mode;


//initialisation du touchscreen
    restoreXY();
   
//initialisation du tftspfd5408
    begin();

//initialisation du VL6180X
//    printf ("Initialisation *********\n");  
//yr
//    pin_mode(VL6180X_I2C_SDA, (PinMode)PullUp);
//    pin_mode(VL6180X_I2C_SCL, (PinMode)PullUp);

    enableVL6180X = 1;
    wait_ms(1); 
    enableVL6180X = 0;
    wait_ms(1); 
    enableVL6180X = 1;
    wait_ms(1);

    /* Creates the 6180XA1 expansion board singleton obj. */
    board = XNucleo6180XA1::instance(device_i2c, D11, D10, D13, D2);

    /* Initializes the 6180XA1 expansion board with default values. */
    status = board->init_board();
    if (status) {
        printf("Failed to init board!\n\r");
        return 0;
    }

//intégration
    mode = MODE_COULEUR_CONSTANTE;
    couleur = RED;
    couleurVariable = BLUE;
    fillRect(0, 0, 240, 280, BLACK); //surface de dessin  
//bouton noir
    fillRect(0, 280, 80, 2, WHITE); // ligne horizontale haut
    fillRect(0, 282, 2, 38, WHITE); // ligne verticale gauche
    fillRect(79, 282, 1, 38, WHITE); // ligne verticale droite
    fillRect(2, 318, 77, 2, WHITE); //ligne horizontale bas
    fillRect(2, 282, 77, 36, BLACK); // centre noir
//bouton rouge
    fillRect(80, 280, 80, 40, WHITE); // moins d'instructions mais plus long
    fillRect(81, 282, 78, 36, RED); // bouton rouge
//bouton cyan
    fillRect(160, 280, 80, 40, WHITE); // moins d'instructions mais plus long
    fillRect(161, 282, 77, 36, BLUE); //bouton bleu
//indicateur
    fillRect(81, 282, 10, 10, GREEN); //couleur rouge par défaut

    while(1) {
        
#ifdef TEST
    printf ("Distance: %d, Lux: %d\n\r", dist, lux);
#endif
            
//tâches du touchscreen
        myled = !myled;

        x = readTouchX();
        y = readTouchY();
        z = detectTouch();
//tâches du tftspfd5408


//tâches d'intégration
        couleurVariable = determineLaCouleur();
//        fillRect(228, 282, 10, 10, couleurVariable); //indicateur de couleur

        if ((z > TOUCH_SEUIL_BAS)&&(z < TOUCH_SEUIL_HAUT))
        {
#ifdef TEST
            pc.printf("x lu %u\t ", x);
            pc.printf("y lu %u\t ", y);
            pc.printf("z lu %u\t ", z);
#endif
            float u = conversion((float)x, XT_G, XE_G, XT_D, XE_D);
            float v = conversion((float)y, YT_B, YE_B, YT_H, YE_H);

#ifdef TEST
            pc.printf("x ecran %f\t ", u);
            pc.printf("y ecran %f\r\n", v);
#endif
            if (v < 280)
            {
                if (mode == MODE_COULEUR_CONSTANTE)
                {
                    fillRect(u, v, 3, 3, couleur);    
                }
                else
                {
                    fillRect(u, v, 3, 3, couleurVariable);                   
                }
            }
            else
            {
                if (u < 80)
                {
                    fillRect(0, 0, 240, 280, BLACK);
                }
                else
                {
                    if (u < 160)
                    {
                        mode = MODE_COULEUR_CONSTANTE;
                        //indicateur RED
                        fillRect(81, 282, 10, 10, GREEN); //couleur rouge par défaut
                        fillRect(161,282, 10, 10, BLUE);

#ifdef TEST
                        pc.printf("couleur: rouge\n\r");
#endif
                    }
                    else
                    {
                        mode = MODE_COULEUR_VARIABLE;
                        //indicateur AUTRE
                        fillRect(81, 282, 10, 10, RED);
                        fillRect(161, 282, 77, 36, BLUE);
                        fillRect(161, 282, 10, 10, GREEN);
                        
#ifdef TEST
                        pc.printf("couleur variable\n\r");
#endif
                    }
                }
            }
        }
    }
}