[apps/hardware_tests and POST] Factorize the tests

This commit is contained in:
Léa Saviot
2019-04-26 12:02:53 +02:00
parent 204be4e7a3
commit 641484457c
9 changed files with 159 additions and 233 deletions

View File

@@ -1,4 +1,5 @@
#include "battery_test_controller.h"
#include <apps/shared/post_and_hardware_tests.h>
#include "../constant.h"
#include "app.h"
extern "C" {
@@ -33,8 +34,9 @@ bool BatteryTestController::handleEvent(Ion::Events::Event event) {
}
void BatteryTestController::viewWillAppear() {
const char * text = Ion::Battery::level() != Ion::Battery::Charge::FULL ? k_batteryNeedChargingText : k_batteryOKText;
KDColor color = Ion::Battery::level() != Ion::Battery::Charge::FULL ? KDColorRed : KDColorGreen;
bool batteryOK = Shared::POSTAndHardwareTests::BatteryOK();
const char * text = batteryOK ? k_batteryOKText : k_batteryNeedChargingText;
KDColor color = batteryOK ? KDColorGreen : KDColorRed;
m_view.setColor(color);
m_view.batteryStateTextView()->setText(text);
updateBatteryState(Ion::Battery::voltage(), Ion::Battery::isCharging());

View File

@@ -1,4 +1,5 @@
#include "lcd_data_test_controller.h"
#include <apps/shared/post_and_hardware_tests.h>
#include <ion/display.h>
using namespace Poincare;
@@ -14,7 +15,7 @@ bool LCDDataTestController::handleEvent(Ion::Events::Event event) {
}
void LCDDataTestController::viewWillAppear() {
bool testOK = test();
bool testOK = Shared::POSTAndHardwareTests::LCDDataOK();
m_view.lcdDataStateTextView()->setText(testOK ? k_lcdDataOKText : k_lcdDataFailTest);
m_view.setColor(testOK ? KDColorGreen : KDColorRed);
}
@@ -34,96 +35,4 @@ void LCDDataTestController::ContentView::layoutSubviews() {
m_lcdDataStateView.setFrame(KDRect(0, 0, Ion::Display::Width, Ion::Display::Height));
}
void colorPixelBuffer(KDColor * pixels, int numberOfPixels, KDColor c) {
for (int i = 0; i < numberOfPixels; i++) {
pixels[i] = c;
}
}
bool LCDDataTestController::test() {
KDColor testColors[] = {
KDColorRed, KDColorGreen, KDColorBlue,
KDColor::RGB24(0xFFFF00), KDColor::RGB24(0xFF00FF), KDColor::RGB24(0x00FFFF),
KDColorWhite, KDColorBlack};
for (KDColor c : testColors) {
if (!testDisplayColor(c)) {
return false;
}
}
return testDisplayBlackWhite();
}
bool LCDDataTestController::testDisplayColor(KDColor c) {
constexpr int stampHeight = 10;
constexpr int stampWidth = 10;
static_assert(Ion::Display::Width % stampWidth == 0, "Stamps must tesselate the display");
static_assert(Ion::Display::Height % stampHeight == 0, "Stamps must tesselate the display");
static_assert(stampHeight % 2 == 0 || stampWidth % 2 == 0, "Even number of XOR needed.");
KDColor stamp[stampWidth*stampHeight];
// Tiling test with pushRect
colorPixelBuffer(stamp, stampWidth * stampHeight, c);
for (int i = 0; i < Ion::Display::Width / stampWidth; i++) {
for (int j = 0; j < Ion::Display::Height / stampHeight; j++) {
Ion::Display::pushRect(KDRect(i * stampWidth, j * stampHeight, stampWidth, stampHeight), stamp);
}
}
if (numberOfNonColoredPixels(c) > invalidPixelsLimit) {
return false;
}
// Test with pushRectUniform
Ion::Display::pushRectUniform(KDRect(KDPointZero, Ion::Display::Width, Ion::Display::Height), c);
if (numberOfNonColoredPixels(c) > invalidPixelsLimit) {
return false;
}
return true;
}
int LCDDataTestController::numberOfNonColoredPixels(KDColor wantedColor) {
constexpr int stampHeight = 10;
constexpr int stampWidth = 10;
static_assert(Ion::Display::Width % stampWidth == 0, "Stamps must tesselate the display");
static_assert(Ion::Display::Height % stampHeight == 0, "Stamps must tesselate the display");
static_assert(stampHeight % 2 == 0 || stampWidth % 2 == 0, "Even number of XOR needed.");
KDColor stamp[stampWidth*stampHeight];
int numberOfInvalidPixels = 0;
for (int i = 0; i < Ion::Display::Width / stampWidth; i++) {
for (int j = 0; j < Ion::Display::Height / stampHeight; j++) {
colorPixelBuffer(stamp, stampWidth * stampHeight, wantedColor == KDColorBlack ? KDColorRed : KDColorBlack);
Ion::Display::pullRect(KDRect(i * stampWidth, j * stampHeight, stampWidth, stampHeight), stamp);
for (int k = 0; k < stampWidth * stampHeight; k++) {
if (stamp[k] != wantedColor) {
numberOfInvalidPixels++;
}
}
}
}
return numberOfInvalidPixels;
}
bool LCDDataTestController::testDisplayBlackWhite() {
Ion::Display::POSTPushBlackWhite();
constexpr int stampHeight = Ion::Display::Height;
constexpr int stampWidth = 2;
static_assert(Ion::Display::Width % stampWidth == 0, "Stamps must tesselate the display");
static_assert(Ion::Display::Height % stampHeight == 0, "Stamps must tesselate the display");
static_assert(stampHeight % 2 == 0 || stampWidth % 2 == 0, "Even number of XOR needed.");
KDColor stamp[stampWidth*stampHeight];
int numberOfInvalidPixels = 0;
for (int i = 0; i < Ion::Display::Width/stampWidth; i++) {
colorPixelBuffer(stamp, stampWidth * stampHeight, KDColorRed);
Ion::Display::pullRect(KDRect(i*stampWidth, 0, stampWidth, stampHeight), stamp);
for (int k = 0; k < stampWidth * stampHeight; k++) {
if (stamp[k] != ((k%2 == 0) ? KDColorWhite : KDColorBlack)) {
numberOfInvalidPixels++;
}
}
}
return numberOfInvalidPixels <= invalidPixelsLimit;
}
}

View File

@@ -43,12 +43,6 @@ private:
};
constexpr static const char * k_lcdDataOKText = "LCD DATA: OK";
constexpr static const char * k_lcdDataFailTest = "LCD DATA: FAIL";
constexpr static int invalidPixelsLimit = 2;
bool test();
bool testDisplayColor(KDColor c);
int numberOfNonColoredPixels(KDColor wantedColor);
bool testDisplayBlackWhite();
ContentView m_view;
};

View File

@@ -1,5 +1,6 @@
#include "vblank_test_controller.h"
#include "../apps_container.h"
#include <apps/shared/post_and_hardware_tests.h>
using namespace Poincare;
@@ -19,6 +20,7 @@ bool VBlankTestController::handleEvent(Ion::Events::Event event) {
* test might end up in an infinite loop, in which case "VBLANK fail" keeps
* being displayed. If the test succeeds, the screen should change very
* quickly to "VBLANK OK". */
Shared::POSTAndHardwareTests::VBlankOK();
for (int i=0; i<6; i++) {
Ion::Display::waitForVBlank();
}

View File

@@ -1,137 +1,24 @@
#include "power_on_self_test.h"
#include <ion/backlight.h>
#include <ion/battery.h>
#include <ion/display.h>
#include <apps/shared/post_and_hardware_tests.h>
#include <ion/led.h>
#include <ion/timing.h>
namespace OnBoarding {
KDColor PowerOnSelfTest::Perform() {
KDColor previousLEDColor = Ion::LED::getColor();
if (!BatteryOK()) {
if (!Shared::POSTAndHardwareTests::BatteryOK()) {
Ion::LED::setColor(KDColorRed);
} else {
Ion::LED::setColor(KDColorBlue);
/* If VBlank test fails, we end up in an infinite loop and the LED will be
* lit up in blue. */
if (VBlankOK() && LCDDataOK()) {
if (Shared::POSTAndHardwareTests::VBlankOK()
&& Shared::POSTAndHardwareTests::LCDDataOK())
{
Ion::LED::setColor(KDColorGreen);
}
}
return previousLEDColor;
}
bool PowerOnSelfTest::BatteryOK() {
return Ion::Battery::level() == Ion::Battery::Charge::FULL;
}
bool PowerOnSelfTest::VBlankOK() {
for (int i=0; i<6; i++) {
Ion::Display::waitForVBlank();
}
return true;
}
bool PowerOnSelfTest::LCDDataOK() {
KDColor testColors[] = {
KDColorRed, KDColorGreen, KDColorBlue,
KDColor::RGB24(0xFFFF00), KDColor::RGB24(0xFF00FF), KDColor::RGB24(0x00FFFF),
KDColorWhite, KDColorBlack};
for (KDColor c : testColors) {
if (!TestDisplayColor(c)) {
return false;
}
}
bool result = TestDisplayBlackWhite();
/* If EPSILON_ONBOARDING_APP == 1, the backlight is not initialized in
* Ion::Device::Board::initPeripherals, so that the LCD test is not visible to
* the user. We thus need to initialize the backlight after the test. Before,
* we push a white rect on the display to hide redrawing glitches. */
Ion::Display::pushRectUniform(KDRect(KDPointZero, Ion::Display::Width, Ion::Display::Height), KDColorWhite);
Ion::Timing::msleep(100);
Ion::Backlight::init();
return result;
}
void PowerOnSelfTest::ColorPixelBuffer(KDColor * pixels, int numberOfPixels, KDColor c) {
for (int i = 0; i < numberOfPixels; i++) {
pixels[i] = c;
}
}
bool PowerOnSelfTest::TestDisplayColor(KDColor c) {
constexpr int stampHeight = 10;
constexpr int stampWidth = 10;
static_assert(Ion::Display::Width % stampWidth == 0, "Stamps must tesselate the display");
static_assert(Ion::Display::Height % stampHeight == 0, "Stamps must tesselate the display");
static_assert(stampHeight % 2 == 0 || stampWidth % 2 == 0, "Even number of XOR needed.");
KDColor stamp[stampWidth*stampHeight];
// Tiling test with pushRect
ColorPixelBuffer(stamp, stampWidth * stampHeight, c);
for (int i = 0; i < Ion::Display::Width / stampWidth; i++) {
for (int j = 0; j < Ion::Display::Height / stampHeight; j++) {
Ion::Display::pushRect(KDRect(i * stampWidth, j * stampHeight, stampWidth, stampHeight), stamp);
}
}
if (NumberOfNonColoredPixels(c) > k_invalidPixelsLimit) {
return false;
}
// Test with pushRectUniform
Ion::Display::pushRectUniform(KDRect(KDPointZero, Ion::Display::Width, Ion::Display::Height), c);
if (NumberOfNonColoredPixels(c) > k_invalidPixelsLimit) {
return false;
}
return true;
}
int PowerOnSelfTest::NumberOfNonColoredPixels(KDColor wantedColor) {
constexpr int stampHeight = 10;
constexpr int stampWidth = 10;
static_assert(Ion::Display::Width % stampWidth == 0, "Stamps must tesselate the display");
static_assert(Ion::Display::Height % stampHeight == 0, "Stamps must tesselate the display");
static_assert(stampHeight % 2 == 0 || stampWidth % 2 == 0, "Even number of XOR needed.");
KDColor stamp[stampWidth*stampHeight];
int numberOfInvalidPixels = 0;
for (int i = 0; i < Ion::Display::Width / stampWidth; i++) {
for (int j = 0; j < Ion::Display::Height / stampHeight; j++) {
ColorPixelBuffer(stamp, stampWidth * stampHeight, wantedColor == KDColorBlack ? KDColorRed : KDColorBlack);
Ion::Display::pullRect(KDRect(i * stampWidth, j * stampHeight, stampWidth, stampHeight), stamp);
for (int k = 0; k < stampWidth * stampHeight; k++) {
if (stamp[k] != wantedColor) {
numberOfInvalidPixels++;
}
}
}
}
return numberOfInvalidPixels;
}
bool PowerOnSelfTest::TestDisplayBlackWhite() {
Ion::Display::POSTPushBlackWhite();
constexpr int stampHeight = Ion::Display::Height;
constexpr int stampWidth = 2;
static_assert(Ion::Display::Width % stampWidth == 0, "Stamps must tesselate the display");
static_assert(Ion::Display::Height % stampHeight == 0, "Stamps must tesselate the display");
static_assert(stampHeight % 2 == 0 || stampWidth % 2 == 0, "Even number of XOR needed.");
KDColor stamp[stampWidth*stampHeight];
int numberOfInvalidPixels = 0;
for (int i = 0; i < Ion::Display::Width/stampWidth; i++) {
ColorPixelBuffer(stamp, stampWidth * stampHeight, KDColorRed);
Ion::Display::pullRect(KDRect(i*stampWidth, 0, stampWidth, stampHeight), stamp);
for (int k = 0; k < stampWidth * stampHeight; k++) {
if (stamp[k] != ((k%2 == 0) ? KDColorWhite : KDColorBlack)) {
numberOfInvalidPixels++;
}
}
}
return numberOfInvalidPixels <= k_invalidPixelsLimit;
}
}

View File

@@ -10,20 +10,6 @@ public:
/* Performs self tests, lights up the LED to indicate the tests results and
* returns the LED color previous to the tests. */
static KDColor Perform();
private:
constexpr static int k_invalidPixelsLimit = 2;
// Tests
static bool BatteryOK();
static bool VBlankOK();
static bool LCDDataOK();
// Test helpers
static bool TestDisplayColor(KDColor c);
static int NumberOfNonColoredPixels(KDColor wantedColor);
static bool TestDisplayBlackWhite();
static void ColorPixelBuffer(KDColor * pixels, int numberOfPixels, KDColor c);
};
}

View File

@@ -46,6 +46,7 @@ app_src += $(addprefix apps/shared/,\
message_view.cpp \
ok_view.cpp \
parameter_text_field_delegate.cpp \
post_and_hardware_tests.cpp \
range_parameter_controller.cpp \
regular_table_view_data_source.cpp \
round_cursor_view.cpp \

View File

@@ -0,0 +1,120 @@
#include "post_and_hardware_tests.h"
#include <ion/backlight.h>
#include <ion/battery.h>
#include <ion/display.h>
#include <ion/timing.h>
namespace Shared {
bool POSTAndHardwareTests::BatteryOK() {
return Ion::Battery::level() == Ion::Battery::Charge::FULL;
}
bool POSTAndHardwareTests::VBlankOK() {
for (int i=0; i<6; i++) {
Ion::Display::waitForVBlank();
}
return true;
}
bool POSTAndHardwareTests::LCDDataOK() {
KDColor testColors[] = {
KDColorRed, KDColorGreen, KDColorBlue,
KDColor::RGB24(0xFFFF00), KDColor::RGB24(0xFF00FF), KDColor::RGB24(0x00FFFF),
KDColorWhite, KDColorBlack};
for (KDColor c : testColors) {
if (!TestDisplayColor(c)) {
return false;
}
}
bool result = TestDisplayBlackWhite();
/* If EPSILON_ONBOARDING_APP == 1, the backlight is not initialized in
* Ion::Device::Board::initPeripherals, so that the LCD test is not visible to
* the user. We thus need to initialize the backlight after the test. Before,
* we push a white rect on the display to hide redrawing glitches. */
Ion::Display::pushRectUniform(KDRect(KDPointZero, Ion::Display::Width, Ion::Display::Height), KDColorWhite);
Ion::Timing::msleep(100);
Ion::Backlight::init();
return result;
}
void POSTAndHardwareTests::ColorPixelBuffer(KDColor * pixels, int numberOfPixels, KDColor c) {
for (int i = 0; i < numberOfPixels; i++) {
pixels[i] = c;
}
}
bool POSTAndHardwareTests::TestDisplayColor(KDColor c) {
constexpr int stampHeight = 10;
constexpr int stampWidth = 10;
static_assert(Ion::Display::Width % stampWidth == 0, "Stamps must tesselate the display");
static_assert(Ion::Display::Height % stampHeight == 0, "Stamps must tesselate the display");
static_assert(stampHeight % 2 == 0 || stampWidth % 2 == 0, "Even number of XOR needed.");
KDColor stamp[stampWidth*stampHeight];
// Tiling test with pushRect
ColorPixelBuffer(stamp, stampWidth * stampHeight, c);
for (int i = 0; i < Ion::Display::Width / stampWidth; i++) {
for (int j = 0; j < Ion::Display::Height / stampHeight; j++) {
Ion::Display::pushRect(KDRect(i * stampWidth, j * stampHeight, stampWidth, stampHeight), stamp);
}
}
if (NumberOfNonColoredPixels(c) > k_invalidPixelsLimit) {
return false;
}
// Test with pushRectUniform
Ion::Display::pushRectUniform(KDRect(KDPointZero, Ion::Display::Width, Ion::Display::Height), c);
if (NumberOfNonColoredPixels(c) > k_invalidPixelsLimit) {
return false;
}
return true;
}
int POSTAndHardwareTests::NumberOfNonColoredPixels(KDColor wantedColor) {
constexpr int stampHeight = 10;
constexpr int stampWidth = 10;
static_assert(Ion::Display::Width % stampWidth == 0, "Stamps must tesselate the display");
static_assert(Ion::Display::Height % stampHeight == 0, "Stamps must tesselate the display");
static_assert(stampHeight % 2 == 0 || stampWidth % 2 == 0, "Even number of XOR needed.");
KDColor stamp[stampWidth*stampHeight];
int numberOfInvalidPixels = 0;
for (int i = 0; i < Ion::Display::Width / stampWidth; i++) {
for (int j = 0; j < Ion::Display::Height / stampHeight; j++) {
ColorPixelBuffer(stamp, stampWidth * stampHeight, wantedColor == KDColorBlack ? KDColorRed : KDColorBlack);
Ion::Display::pullRect(KDRect(i * stampWidth, j * stampHeight, stampWidth, stampHeight), stamp);
for (int k = 0; k < stampWidth * stampHeight; k++) {
if (stamp[k] != wantedColor) {
numberOfInvalidPixels++;
}
}
}
}
return numberOfInvalidPixels;
}
bool POSTAndHardwareTests::TestDisplayBlackWhite() {
Ion::Display::POSTPushBlackWhite();
constexpr int stampHeight = Ion::Display::Height;
constexpr int stampWidth = 2;
static_assert(Ion::Display::Width % stampWidth == 0, "Stamps must tesselate the display");
static_assert(Ion::Display::Height % stampHeight == 0, "Stamps must tesselate the display");
static_assert(stampHeight % 2 == 0 || stampWidth % 2 == 0, "Even number of XOR needed.");
KDColor stamp[stampWidth*stampHeight];
int numberOfInvalidPixels = 0;
for (int i = 0; i < Ion::Display::Width/stampWidth; i++) {
ColorPixelBuffer(stamp, stampWidth * stampHeight, KDColorRed);
Ion::Display::pullRect(KDRect(i*stampWidth, 0, stampWidth, stampHeight), stamp);
for (int k = 0; k < stampWidth * stampHeight; k++) {
if (stamp[k] != ((k%2 == 0) ? KDColorWhite : KDColorBlack)) {
numberOfInvalidPixels++;
}
}
}
return numberOfInvalidPixels <= k_invalidPixelsLimit;
}
}

View File

@@ -0,0 +1,25 @@
#ifndef SHARED_POST_AND_HARDWARE_TESTS_H
#define SHARED_POST_AND_HARDWARE_TESTS_H
#include <kandinsky/color.h>
namespace Shared {
class POSTAndHardwareTests {
public:
static bool BatteryOK();
static bool VBlankOK();
static bool LCDDataOK();
private:
constexpr static int k_invalidPixelsLimit = 2;
static bool TestDisplayColor(KDColor c);
static int NumberOfNonColoredPixels(KDColor wantedColor);
static bool TestDisplayBlackWhite();
static void ColorPixelBuffer(KDColor * pixels, int numberOfPixels, KDColor c);
};
}
#endif