I have copied in some of the code from the Arduino source but I still can't get this loop to behave. In loopTask(), if I add a 2 second vTaskDelay(), I see some text on the VGA display. If I remove it, it doesn't work.
Am I missing something from the standard Arduino setup() and loop() ?
Code: Select all
#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/gpio.h"
#include "sdkconfig.h"
#include "esp_task.h"
#include "esp_task_wdt.h"
#include <Time.h>
#include "fabgl.h"
fabgl::VGAController DisplayController;
fabgl::Canvas canvas(&DisplayController);
#define DOUBLEBUFFERING 1
struct Test {
virtual ~Test() { };
virtual void update() = 0;
virtual bool nextState() = 0;
virtual int testState() = 0;
virtual char const * name() = 0;
};
#include "ballstest.h"
#include "polygonstest.h"
#include "spritestest.h"
void setupDisplay()
{
DisplayController.begin();
DisplayController.setResolution(VGA_320x200_75Hz, -1, -1, DOUBLEBUFFERING);
//DisplayController.moveScreen(-8, 0);
// get a font for about 40x14 text screen
canvas.selectFont(&fabgl::FONT_8x8);
canvas.setGlyphOptions(GlyphOptions().FillBackground(true));
}
int pds = 0;
void updateDisplay()
{
static int64_t stime = esp_timer_get_time();
static int FPS = 0;
static int FPSCounter = 0;
static int testIndex = 0;
static Test * test = new BallsTest;
if (test->nextState() == false) {
delete test;
++testIndex;
switch (testIndex) {
case 1:
test = new PolygonsTest;
break;
case 2:
test = new SpritesTest;
break;
default:
testIndex = 0;
test = new BallsTest;
break;
}
}
if (esp_timer_get_time() - stime > 1000000) {
// calculate FPS
FPS = FPSCounter;
stime = esp_timer_get_time();
FPSCounter = 0;
}
++FPSCounter;
test->update();
pds ++;
// display test state and FPS
canvas.setPenColor(Color::Blue);
canvas.setBrushColor(Color::Yellow);
canvas.drawTextFmt(80, 5, " %d My %s at %d FPS PDS: %d", test->testState(), test->name(), FPS, pds);
if (DOUBLEBUFFERING)
canvas.swapBuffers();
}
extern void serialEventRun(void) __attribute__((weak));
TaskHandle_t loopTaskHandle = NULL;
bool loopTaskWDTEnabled = false;
void enableLoopWDT(){
if(loopTaskHandle != NULL){
if(esp_task_wdt_add(loopTaskHandle) != ESP_OK){
// PDS> log_e("Failed to add loop task to WDT");
} else {
loopTaskWDTEnabled = true;
}
}
}
#define ARDUINO_ISR_ATTR
unsigned long ARDUINO_ISR_ATTR millis()
{
return (unsigned long) (esp_timer_get_time() / 1000ULL);
}
void yieldIfNecessary(void){
static uint64_t lastYield = 0;
uint64_t now = millis();
if((now - lastYield) > 2000) {
lastYield = now;
vTaskDelay(5); //delay 1 RTOS tick
}
}
void loopTask(void *pvParameters) {
setupDisplay();
for(;;)
{
//#if CONFIG_FREERTOS_UNICORE
yieldIfNecessary();
//#endif
if(loopTaskWDTEnabled){
esp_task_wdt_reset();
}
updateDisplay();
//if (serialEventRun) serialEventRun();
//vTaskDelay(2000 / portTICK_PERIOD_MS); // The only way I can get something to appear
}
}
extern "C" void app_main(void)
{
// PDS> Do I need this?
enableLoopWDT();
//xTaskCreateUniversal(loopTask, "loopTask", getArduinoLoopTaskStackSize(), NULL, 1, &loopTaskHandle, ARDUINO_RUNNING_CORE);
xTaskCreatePinnedToCore(
loopTask
, "loopTask"
, 2048 // Stack size
, NULL // When no parameter is used, simply pass NULL
, 1 // Priority
, &loopTaskHandle // With task handle we will be able to manipulate with this task.
, tskNO_AFFINITY // Core on which the task will run
);
}