Production Test Program (PTP) for the LPC4088 Experiment Base Board

Dependencies:   EALib I2S LM75B SDFileSystem mbed

Revision:
1:47680ec5d783
Parent:
0:0d5190d379d3
Child:
2:2f4b7535ceb3
--- a/main.cpp	Mon Aug 25 13:15:27 2014 +0000
+++ b/main.cpp	Wed Aug 27 14:24:59 2014 +0000
@@ -11,18 +11,72 @@
 #include "TextLCD.h"
 #include "DmTftHX8353C.h"
 #include "BubbleDemo.h"
+#include "AR1021I2C.h"
+#include "Graphics.h"
+
+#include "LcdController.h"
+#include "EaLcdBoardGPIO.h"
+#include "sdram.h"
 
 /******************************************************************************
  * Typedefs and defines
  *****************************************************************************/
 
+#define ACC_XMIN  (1<<0)  
+#define ACC_XMAX  (1<<1)  
+#define ACC_YMIN  (1<<2)  
+#define ACC_YMAX  (1<<3)  
+#define ACC_ZMIN  (1<<4)  
+#define ACC_ZMAX  (1<<5)  
+  
+#define ACC_MIN_LIMIT  (-50)
+#define ACC_MAX_LIMIT  ( 50)
+
 #define BUTTON_PRESSED   0
 #define BUTTON_RELEASED  1
 
 #define LED_ON   0
 #define LED_OFF  1
 
-#define handleError(__a, __b)  printf("Error: %s\n", (__b)); mbed_die()
+#if 0
+    // Enters eternal loop
+    #define handleError(__a, __b) do { \
+        printf("Error " #__a ": %s\n", (__b)); \
+        resetLEDs(); \
+        ledRed = LED_ON; \
+        ledGreen = LED_OFF; \
+        ledBlue = LED_OFF; \
+        mbed_die(); \
+    } while(0)
+    
+    #define showTestResult() do {} while(0)   // Never used in this setup
+#else
+    bool allTestsPassed = true;
+    // Leaves error handling to the end of the program
+    #define handleError(__a, __b) do { \
+        printf("Error " #__a ": %s\n", (__b)); \
+        resetLEDs(); \
+        *ledRed = LED_ON; \
+        *ledGreen = LED_OFF; \
+        *ledBlue = LED_OFF; \
+        allTestsPassed = false; \
+        return; \
+    } while(0)
+    
+    #define showTestResult() do { \
+        resetLEDs(); \
+        *ledRed = LED_OFF; \
+        *ledGreen = LED_OFF; \
+        *ledBlue = LED_OFF; \
+        if (allTestsPassed) { \
+            printf("\n\nTest Result: PASSED\n\n"); \
+            *ledGreen = LED_ON; \
+        } else { \
+            printf("\n\nTest Result: FAILED\n\n"); \
+            *ledRed = LED_ON; \
+        } \
+    } while(0)
+#endif
 
 #define waitForButtonClick()  do {while(button.read() == BUTTON_RELEASED); while(button.read() == BUTTON_PRESSED);} while(false)
 
@@ -30,25 +84,47 @@
  * Local variables
  *****************************************************************************/
 
-//MCIFileSystem mcifs("mci");//, P4_16);
-SDFileSystem spifs(p5, p6, p7, p8, "spi"); // mosi, miso, sclk, cs
-
 DigitalOut myled(LED1);
 DigitalIn  button(p23);
 
 SPI shiftreg(p5, p6, p7);  // mosi, miso, sclk,
 DigitalOut shiftregCS(p30);
 
-DigitalOut ledRed(p25);
-DigitalOut ledGreen(p28);
-DigitalOut ledBlue(p26);
+DigitalOut* ledRed = NULL;
+DigitalOut* ledGreen = NULL;
+DigitalOut* ledBlue = NULL;
 
 /******************************************************************************
  * Local functions
  *****************************************************************************/
 
+static void resetLEDs()
+{
+    // Some peripherals may interfer with the RGB LED and as a result it
+    // may be needed to reinitialize them so that PIN is again an GPIO.
+    if (ledRed != NULL) {
+        delete ledRed;
+    }
+    if (ledGreen != NULL) {
+        delete ledGreen;
+    }
+    if (ledBlue != NULL) {
+        delete ledBlue;
+    }
+    ledRed = new DigitalOut(p25);
+    ledGreen = new DigitalOut(p28);
+    ledBlue = new DigitalOut(p26);
+
+    *ledRed = LED_OFF;
+    *ledGreen = LED_OFF;
+    *ledBlue = LED_OFF;
+}
+
 static void test_micro_sd_card_mci()
 {
+  // The LPC4088 Experiment Base Board does not have the CardDetect signal
+  // available so it must be set to NC here to work.
+  MCIFileSystem mcifs("mci", NC);
   FILE* fp = fopen("/mci/message.txt", "r");
   if (fp != NULL) {
     char buf[20];
@@ -69,6 +145,7 @@
 
 static void test_micro_sd_card_spi()
 {
+  SDFileSystem spifs(p5, p6, p7, p8, "spi"); // mosi, miso, sclk, cs
   FILE* fp = fopen("/spi/message.txt", "r");
   if (fp != NULL) {
     char buf[20];
@@ -89,6 +166,52 @@
 
 static void test_acc()
 {
+#if 1
+  MMA7455 sensor(P0_27, P0_28);
+  
+  //Try to initialize the accelerometer
+  if (!sensor.setMode(MMA7455::ModeMeasurement)) {
+     handleError(STATE_ERR_ACC, "Unable to set mode for MMA7455!\n");
+  }
+  
+  if (!sensor.calibrate()) {
+     handleError(STATE_ERR_ACC, "Failed to calibrate MMA7455!\n");
+  }
+
+  int val[3] = {    0,    0,    0};
+  int max[3] = {-1000,-1000,-1000};
+  int min[3] = { 1000, 1000, 1000};
+  int i;
+  Timer t;
+  t.start();
+  while (t.read() < 5) {
+    if (!sensor.read(val[0], val[1], val[2])) {
+      handleError(STATE_ERR_ACC, "Failed to read accelerometer data!\n");
+    }
+    printf("ACC: x,y,z = {%5d, %5d, %5d}\n", val[0], val[1], val[2]);
+    for (i = 0; i < 3; i++) {
+      if (val[i] < min[i]) {
+        min[i] = val[i];
+      }
+      if (val[i] > max[i]) {
+        max[i] = val[i];
+      }
+    }
+    for (i = 0; i < 3; i++) {
+      if ((max[i] - min[i]) < 2) {
+        break;
+      }
+      if (i == 2) {
+        printf("All three axis work\n");
+        return;
+      }
+    }
+    wait(0.1);
+  }
+  printf("Not enough variation X {%d..%d}, Y {%d..%d}, Z {%d..%d}!\n",
+              min[0], max[0], min[1], max[1], min[2], max[2]);
+  handleError(STATE_ERR_ACC, "Accelerometer data invalid\n");
+#else
   MMA7455 sensor(P0_27, P0_28);
   
   //Try to initialize the accelerometer
@@ -104,37 +227,73 @@
      handleError(STATE_ERR_ACC, "Failed to calibrate MMA7455!\n");
   }
   
-  printf("Printing values for the next 5 seconds...\n");
+  printf("Now tilt the board in all directions (max 10 seconds)...\n");
   int x=0, y=0, z=0;
+  uint8_t done = 0;
+  char msg[30] = {0};
   
   Timer t;
   t.start();
-  while (t.read() < 6) {
+  while ((t.read() < 10) && (done != 0x3f)) {
     if (!sensor.read(x, y, z)) {
       handleError(STATE_ERR_ACC, "Failed to read accelerometer data!\n");
     }
-    printf("ACC: x,y,z = {%5d, %5d, %5d}\n", x, y, z);
+    printf("ACC: x,y,z = {%5d, %5d, %5d} %s\n", x, y, z, msg);
+    if ((x < ACC_MIN_LIMIT) && !(done & ACC_XMIN)) {
+        done |= ACC_XMIN;
+        printf("Tilted XMIN\n");
+    } else if ((x > ACC_MAX_LIMIT) && !(done & ACC_XMAX)) {
+        done |= ACC_XMAX;
+        printf("Tilted XMAX\n");
+    }
+    if ((y < ACC_MIN_LIMIT) && !(done & ACC_YMIN)) {
+        done |= ACC_YMIN;
+        printf("Tilted YMIN\n");
+    } else if ((y > ACC_MAX_LIMIT) && !(done & ACC_YMAX)) {
+        done |= ACC_YMAX;
+        printf("Tilted XMAX\n");
+    }
+    if ((z < ACC_MIN_LIMIT) && !(done & ACC_ZMIN)) {
+        done |= ACC_ZMIN;
+        printf("Tilted ZMIN\n");
+    } else if ((z > ACC_MAX_LIMIT) && !(done & ACC_ZMAX)) {
+        done |= ACC_ZMAX;
+        printf("Tilted ZMAX\n");
+    }
+    wait(0.1);
   }
   printf("Done with ACC tests!\n");
+#endif
 }
 
 static void test_lm75()
 {
   //Create an LM75B object at 0x92/0x93 (ADDRESS_1)
   LM75B sensor(P0_27, P0_28, LM75B::ADDRESS_1);
-  
+
+  printf("Testing LM75 temperature sensor...\n");
+    
     //Try to open the LM75B
     if (sensor.open()) {
         printf("LM75 Device detected!\n");
  
         int i = 10;
         while (i--) {
+            float f = (float)sensor;
             //Print the current temperature
-            printf("Temp = %.3f\n", (float)sensor);
+            printf("Temp = %.3f\n", f);
  
+            if ((f >= 15) && (f <= 45)) {
+                printf("Temp in 15..45 range - test passed\n");
+                break;
+            }
+            
             //Sleep for 0.5 seconds
             wait(0.5);
         }
+        if (i == 0) {
+            handleError(STATE_ERR_LM75, "LM75 No temp in range 15..45!\n");
+        }
     } else {
         handleError(STATE_ERR_LM75, "LM75 Device not detected!\n");
     }  
@@ -143,13 +302,27 @@
 static void test_trimpot()
 {
   AnalogIn trimpot(p15);
+  bool min = false;
+  bool max = false;
 
   printf("Reading trimpot for 5 seconds...\n");  
 
   for (int i = 0; i < 50; i++) {
-    printf("Trimpot = %.3f\n", trimpot.read());
+    float f = trimpot.read();
+    printf("Trimpot = %.3f\n", f);
+    if (f < 0.01f) {
+        min = true;
+    } else if (f > 0.99f) {
+        max = true;
+    }
+    if (min && max) {
+        printf("Test passed\n");
+        return;
+    }
+    
     wait(0.1);
-  }  
+  }
+  handleError(STATE_ERR_TRIMPOT, "Trimpot does not reach limits (0.01 - 0.99)!\n");
 }
 
 static void outputShiftReg(uint8_t val)
@@ -217,47 +390,57 @@
     }
     if (mask == 0x1F) {
         printf("All directions tested. Done!\n");
-        break;
+        return;
     }
     wait(0.1);
-  }  
+    if (i%10 == 0) {
+      printf("%ds\n", (100-i)/10);
+    }
+  }
+  handleError(STATE_ERR_JOYSTICK, "Failed to detect all joystick directions\n");
 }
 
 static void test_rgb()
 {
-  printf("All off. Press button to continue\n");
-  ledRed = LED_OFF;
-  ledGreen = LED_OFF;
-  ledBlue = LED_OFF;
+  printf("LED Tests: All off. Press button to continue\n");
+  *ledRed = LED_OFF;
+  *ledGreen = LED_OFF;
+  *ledBlue = LED_OFF;
   waitForButtonClick();
 
-  printf("RED on. Press button to continue\n");
-  ledRed = LED_ON;
-  ledGreen = LED_OFF;
-  ledBlue = LED_OFF;
+  printf("LED Tests: RED on. Press button to continue\n");
+  *ledRed = LED_ON;
+  *ledGreen = LED_OFF;
+  *ledBlue = LED_OFF;
   waitForButtonClick();
   
-  printf("GREEN on. Press button to continue\n");
-  ledRed = LED_OFF;
-  ledGreen = LED_ON;
-  ledBlue = LED_OFF;
+  printf("LED Tests: GREEN on. Press button to continue\n");
+  *ledRed = LED_OFF;
+  *ledGreen = LED_ON;
+  *ledBlue = LED_OFF;
   waitForButtonClick();
   
-  printf("BLUE on. Press button to continue\n");
-  ledRed = LED_OFF;
-  ledGreen = LED_OFF;
-  ledBlue = LED_ON;
+  printf("LED Tests: BLUE on. Press button to continue\n");
+  *ledRed = LED_OFF;
+  *ledGreen = LED_OFF;
+  *ledBlue = LED_ON;
   waitForButtonClick();
   
-  printf("All on. Press button to continue\n");
-  ledRed = LED_OFF;
-  ledGreen = LED_OFF;
-  ledBlue = LED_OFF;
+  printf("LED Tests: All on. Press button to continue\n");
+  *ledRed = LED_ON;
+  *ledGreen = LED_ON;
+  *ledBlue = LED_ON;
   waitForButtonClick();
+
+  // Turn them off again
+  *ledRed = LED_OFF;
+  *ledGreen = LED_OFF;
+  *ledBlue = LED_OFF;
 }
 
 static void test_audio()
 {
+    printf("Testing audio...\n");
     WM8731 audio(P0_27, P0_28);
     if (!audio.writeCmd(WM8731::REG_R15_RESET, 0x0000)) {
         handleError(STATE_ERR_AUDIO, "Failed to send command to audio codec\n");
@@ -301,45 +484,197 @@
     bubbleDemo.run(750, 20);
 }
 
+static void drawBars(int w, int h, uint32_t frameBuf)
+{
+    uint16_t* p = (uint16_t*)frameBuf;
+    int third = w/3;
+    for (int y = 0; y < h; y++) {
+        int x;
+        for (x = 0; x < third; x++) {
+            *p = 0xf800;
+            p++;
+        }
+        for (; x < 2*third; x++) {
+            *p = 0x07e0;
+            p++;
+        }
+        for (; x < w; x++) {
+            *p = 0x001f;
+            p++;
+        }
+    }
+}
+
+static void calibrate_drawMarker(Graphics &g, uint16_t x, uint16_t y, bool erase)
+{
+  uint16_t color = (erase ? 0x0000 : 0xffff);
+  g.put_line(x-15, y, x+15, y, color);
+  g.put_line(x, y-15, x, y+15, color);
+  g.put_circle(x, y, color, 10, false);
+}
+
+static void calibrate_display(TouchPanel* tp, uint32_t framebuffer, LcdController::Config &lcd)
+{
+  bool morePoints = true;
+  uint16_t x, y;
+  int point = 0;
+  Graphics g((uint16_t*)framebuffer, lcd.width, lcd.height);
+  if (!tp->init(lcd.width, lcd.height)) {
+    handleError(STATE_ERR_TOUCH, "Failed to initialize touch controller\n");
+  }
+  if (!tp->calibrateStart()) {
+    handleError(STATE_ERR_TOUCH, "Failed to start calibration\n");
+  }  
+  while (morePoints) {
+    if (point++ > 0) {
+      // erase old location
+      calibrate_drawMarker(g, x, y, true);
+    }
+    if (!tp->getNextCalibratePoint(&x, &y)) {
+      handleError(STATE_ERR_TOUCH, "Failed to get calibration point\n");
+    }
+      calibrate_drawMarker(g, x, y, false);
+    if (!tp->waitForCalibratePoint(&morePoints, 0)) {
+      handleError(STATE_ERR_TOUCH, "Failed to get user click\n");
+    }
+  }
+  
+  // erase old location
+  calibrate_drawMarker(g, x, y, true);
+  
+  // allow user to draw for 5 seconds
+  Timer t;
+  t.start();
+  TouchPanel::touchCoordinate_t tc;
+  while(t.read() < 6) {
+    if (tp->read(tc)) {
+      //printf("TC: x,y,z = {%5d, %5d, %5d}\n", tc.x, tc.y, tc.z);
+      if (tc.z) {
+        g.put_dot(tc.x, tc.y, 0xffff);
+      }
+    }
+  }
+}
+
+static void test_Display()
+{
+    if (sdram_init() == 1) {
+        handleError(STATE_ERR_MEM, "Failed to initialize SDRAM\n");
+    }
+    
+    // Test of display attached with FPC connector, 0.5mm pitch
+    EaLcdBoard::Result result;
+    LcdController::Config lcdCfg(40, 5, 2, 480, 8, 8, 2, 272, false, false, true, true, 1, LcdController::Bpp_16_565, 9000000, LcdController::Tft, false);
+    char* initStr = "v1,cd0,c50,cc0,c30,d100,c31,d100,cd1,d10,o,c51,cc100";
+    EaLcdBoardGPIO lcdBoard(P0_27, P0_28);
+    int num = lcdCfg.width * lcdCfg.height * 2;
+    
+    uint32_t frameBuf = (uint32_t) malloc(num);
+    if (frameBuf == 0) {
+        handleError(STATE_ERR_MEM, "Failed to allocate memory for framebuffer\n");
+    }
+    drawBars(lcdCfg.width, lcdCfg.height, frameBuf);
+
+    result = lcdBoard.open(&lcdCfg, initStr);
+    if (result != EaLcdBoard::Ok) {
+        printf("Error Code: %d\n", result);
+        handleError(STATE_ERR_MEM, "Failed to open display\n");
+    }
+
+    result = lcdBoard.setFrameBuffer(frameBuf);
+    if (result != EaLcdBoard::Ok) {
+        printf("Error Code: %d\n", result);
+        handleError(STATE_ERR_MEM, "Failed to set framebuffer\n");
+    }
+        
+    printf("Initialized. Control contrast with right trimpot (8 seconds)\n");
+    AnalogIn trimpot(p15);
+    Timer t;
+    t.start();
+    int delays = 0;
+    float last = -0.365;
+    while (t.read() < 8) {
+        float f = trimpot.read();
+        if (f != last) {
+            last = f;
+            lcdBoard.setBC(100*f);
+        }
+        wait(0.1);
+        if (delays%10 == 0) {
+            printf("%ds\n", (80-delays)/10);
+        }
+        delays++;
+    }
+    
+    AR1021I2C touch(P0_27, P0_28, P2_25);
+    int vh,vl,r,ty;
+    if (touch.info(&vh,&vl,&r,&ty)) {
+        printf("Touch info: v%d.%d, %d-bit resolution, type 0x%x\n", vh, vl, r, ty);
+    } else {
+        printf("Failed to read touch information\n");
+    }
+
+    printf("Calibrate display\n");
+    calibrate_display(&touch, frameBuf, lcdCfg);
+    if (allTestsPassed) {
+        memset((uint8_t*)frameBuf, 0x03, num); // GREEN
+    } else {
+        memset((uint8_t*)frameBuf, 0xe0, num); // RED
+    }
+}
+
+static void setupSerial(int baudrate)
+{
+    // This works because both the default serial (used by printf) and the s instance
+    // (used by s.printf) would use the same underlying UART code so setting the baudrate
+    // in one affects the other.
+    Serial s(USBTX, USBRX);
+    s.baud(baudrate);
+}
+
 int main() {
-    printf("hello! " __DATE__ " at " __TIME__ "\n");
+    setupSerial(115200);
+    printf("\n"
+           "---\n"
+           "Production Test Program: LPC4088 Experiment Base Board\n"
+           "Build Date: " __DATE__ " at " __TIME__ "\n"
+           "\n");
     
     shiftregCS = 1;    
     button.mode(PullUp);
     
-    ledRed = LED_OFF;
-    ledGreen = LED_OFF;
-    ledBlue = LED_OFF;
+    resetLEDs();
       
     outputShiftReg(0x0);
     
      //startup flash behaviour
      for(int i=0; i<10; i++)
      {
-       ledRed = LED_ON;
+       *ledRed = LED_ON;
        wait(0.05);
-       ledRed = LED_OFF;
+       *ledRed = LED_OFF;
        wait(0.05);
      }
      wait(1.0);
      for(int i=0; i<10; i++)
      {
-       ledGreen = LED_ON;
+       *ledGreen = LED_ON;
        wait(0.05);
-       ledGreen = LED_OFF;
+       *ledGreen = LED_OFF;
        wait(0.05);
      }
      wait(1.0);
      for(int i=0; i<10; i++)
      {
-       ledBlue = LED_ON;
+       *ledBlue = LED_ON;
        wait(0.05);
-       ledBlue = LED_OFF;
+       *ledBlue = LED_OFF;
        wait(0.05);
      }
      wait(1.0);    
 
-    //test_micro_sd_card_mci();
+    test_micro_sd_card_mci();
+    resetLEDs(); // MCI interface disables the RGB LED
 //    test_micro_sd_card_spi();
     test_acc();
     test_lm75();
@@ -349,7 +684,12 @@
     test_audio();
     //test_TextLCD();
     //test_DisplayModule();
-    waitForButtonClick();
+
+    test_Display();
+     
+    showTestResult();
+     
+    //waitForButtonClick();
 
     while(1) {
         test_shiftreg();