Browse Source

Fixed sleep mode issues

* Main loop now has simple state machine for easier flow understanding
* Expose GPIO pin button mappings in input.h
* Ignore potential wake input until all buttons released
* Monitor all buttons for wake
* Add more cases for wakeup reason
* Reset input to what Odroid_PollInput() expects after waking
* Removed commented tile draw code
master
Macoy Madson 3 years ago
parent
commit
de1bf7d26b
  1. 462
      app/src/main.c
  2. 16
      app/src/odroid/input.c
  3. 11
      app/src/odroid/input.h
  4. 57
      app/src/odroid/sleep.c

462
app/src/main.c

@ -20,7 +20,7 @@ static bool drawTimeSinceBoot = false;
static bool drawFrameRate = true;
/* static bool printInput = true; */
static bool printInput = false;
static bool printInput = true;
static bool enableLowFrameRate = true;
@ -38,137 +38,22 @@ static uint16_t gFramebuffer[LCD_WIDTH * LCD_HEIGHT];
/* 0x0000, */
/* }; */
static const uint16_t darkPalette[4] =
{
0x0000,
0xAA52,
0x55AD,
0xFFFF,
static const uint16_t darkPalette[4] = {
0x0000,
0xAA52,
0x55AD,
0xFFFF,
};
static const uint16_t* palette = darkPalette;
static const uint8_t tiles[][16*16] =
{
// White
{
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
},
// Light Grey
{
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,1,1,1,1,1,1,1,1,1,1,1,1,0,0,
0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,
0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,
0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,
0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,
0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,
0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,
0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,
0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,
0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,
0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,
0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,
0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,
0,0,1,1,1,1,1,1,1,1,1,1,1,1,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
},
// Dark Grey
{
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,2,2,2,2,2,2,2,2,2,2,2,2,0,0,
0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,
0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,
0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,
0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,
0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,
0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,
0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,
0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,
0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,
0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,
0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,
0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,
0,0,2,2,2,2,2,2,2,2,2,2,2,2,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
},
// Black
{
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,3,3,3,3,3,3,3,3,3,3,3,3,0,0,
0,3,3,3,3,3,3,3,3,3,3,3,3,3,3,0,
0,3,3,3,3,3,3,3,3,3,3,3,3,3,3,0,
0,3,3,3,3,3,3,3,3,3,3,3,3,3,3,0,
0,3,3,3,3,3,3,3,3,3,3,3,3,3,3,0,
0,3,3,3,3,3,3,3,3,3,3,3,3,3,3,0,
0,3,3,3,3,3,3,3,3,3,3,3,3,3,3,0,
0,3,3,3,3,3,3,3,3,3,3,3,3,3,3,0,
0,3,3,3,3,3,3,3,3,3,3,3,3,3,3,0,
0,3,3,3,3,3,3,3,3,3,3,3,3,3,3,0,
0,3,3,3,3,3,3,3,3,3,3,3,3,3,3,0,
0,3,3,3,3,3,3,3,3,3,3,3,3,3,3,0,
0,3,3,3,3,3,3,3,3,3,3,3,3,3,3,0,
0,0,3,3,3,3,3,3,3,3,3,3,3,3,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
},
};
static int tileBuffer[15][40] =
{
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 3, 3, 0, 0, 0, 0, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0},
{0, 0, 3, 0, 0, 0, 3, 3, 3, 0, 0, 0, 3, 3, 3, 3, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0},
{2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2},
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
};
void DrawTile(int index, int x, int y)
void updateBatteryIndicator()
{
int startX = x * 16;
int startY = y * 16;
for (int row = 0; row < 16; ++row)
{
for (int col = 0; col < 16; ++col)
{
uint8_t paletteIndex = tiles[index][row * 16 + col];
int screenY = startY + row;
int screenX = startX + col;
uint16_t color = palette[paletteIndex];
gFramebuffer[screenY * LCD_WIDTH + screenX] = color;
}
}
float batteryPercentage = Odroid_ReadBatteryLevelPercentage();
if (batteryPercentage < 15.f)
Odroid_EnableBatteryLight();
else
Odroid_DisableBatteryLight();
}
void app_main(void)
@ -184,7 +69,6 @@ void app_main(void)
/* uint8_t frameIndex = 0; */
/* char snapFilename[20]; */
/* int xLeft = 0; */
bool timerRunning = false;
int64_t timerStartMicroSecs = 0;
@ -197,213 +81,189 @@ void app_main(void)
Odroid_Input lastFrameInput = {0};
bool sleepMode = false;
bool backlightOn = true;
bool waitForSleepActivateRelease = false;
typedef enum AppState
{
Sleeping,
Awake_WaitingForWakeButtonRelease,
Awake,
} AppState;
AppState state = Awake;
while (true)
{
memset(gFramebuffer, palette[0], 320 * 240 * 2);
if (state == Awake || state == Awake_WaitingForWakeButtonRelease)
{
float batteryPercentage = Odroid_ReadBatteryLevelPercentage();
if (batteryPercentage < 15.f)
Odroid_EnableBatteryLight();
else
Odroid_DisableBatteryLight();
}
memset(gFramebuffer, palette[0], 320 * 240 * 2);
int64_t currentTimeMicroSecs = esp_timer_get_time();
updateBatteryIndicator();
Odroid_Input input = Odroid_PollInput();
bool hasInputsThisFrame = Odroid_HasAnyInput(&input);
if (hasInputsThisFrame)
timeSinceLastInputMicroSecs = esp_timer_get_time();
int64_t currentTimeMicroSecs = esp_timer_get_time();
if (printInput)
Odroid_PrintInputState(&input);
Odroid_Input input = Odroid_PollInput();
bool hasInputsThisFrame = Odroid_HasAnyInput(&input);
if (hasInputsThisFrame)
timeSinceLastInputMicroSecs = esp_timer_get_time();
// Sleep mode
if (sleepMode)
{
// Try to save battery while still listening to inputs
while (Odroid_EnterLightSleep(lightSleepMicroseconds))
if (printInput)
Odroid_PrintInputState(&input);
if (state == Awake_WaitingForWakeButtonRelease)
{
float batteryPercentage = Odroid_ReadBatteryLevelPercentage();
if (batteryPercentage < 15.f)
Odroid_EnableBatteryLight();
else
Odroid_DisableBatteryLight();
if (!hasInputsThisFrame)
{
state = Awake;
lastFrameInput = input;
}
}
sleepMode = false;
timeSinceLastInputMicroSecs = esp_timer_get_time();
bool buttonPressedForSleepMode = false;
continue;
}
if (!sleepMode && !backlightOn)
{
Odroid_BacklightInit();
backlightOn = true;
}
if (input.a && !lastFrameInput.a)
{
printf("Pause timer\n");
timerRunning = !timerRunning;
// Only take inputs after wake button released
if (state == Awake)
{
if (input.a && !lastFrameInput.a)
{
printf("Toggle timer\n");
timerRunning = !timerRunning;
if (timerRunning)
timerStartMicroSecs = currentTimeMicroSecs;
else
timerTotalMicroSecsPrePause += currentTimeMicroSecs - timerStartMicroSecs;
}
if (input.start && !lastFrameInput.start)
{
printf("Reset timer\n");
timerRunning = false;
timerTotalMicroSecsPrePause = 0;
}
buttonPressedForSleepMode = (lastFrameInput.b && !input.b);
}
if (timerRunning)
timerStartMicroSecs = currentTimeMicroSecs;
else
timerTotalMicroSecsPrePause += currentTimeMicroSecs - timerStartMicroSecs;
bool noInputsSleepMode =
currentTimeMicroSecs - timeSinceLastInputMicroSecs > autoSleepModeMicroseconds;
if (noInputsSleepMode || buttonPressedForSleepMode)
{
state = Sleeping;
printf("Entering sleep reason: ");
if (noInputsSleepMode)
printf("No inputs in %lld seconds ", autoSleepModeMicroseconds / 1000000);
if (buttonPressedForSleepMode)
printf("Sleep button pressed ");
printf("\n");
}
/* esp_err_t err = ledc_stop(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_0, 0); */
/* if (err != ESP_OK) */
/* { */
/* printf("%s: ledc_stop failed.\n", __func__); */
/* } */
}
// Timer
{
char string[18];
int64_t currentTimeMicroSecs = esp_timer_get_time();
float timerSeconds = timerRunning ?
((timerTotalMicroSecsPrePause +
(currentTimeMicroSecs - timerStartMicroSecs)) /
1000000.f) :
timerTotalMicroSecsPrePause / 1000000.f;
snprintf(string, ArraySize(string), "%d:%.2d", (int)timerSeconds / 60,
(int)timerSeconds % 60);
DrawText(gFramebuffer, string, ArraySize(string), 3, 5, palette[3]);
if (!timerRunning)
{
snprintf(string, ArraySize(string), "Paused");
DrawText(gFramebuffer, string, ArraySize(string), 3, 6, palette[3]);
}
}
if (input.start && !lastFrameInput.start)
{
printf("Reset timer\n");
// Battery
if (drawBatteryPercent)
{
char string[10];
snprintf(string, ArraySize(string), "B: %.0f", Odroid_ReadBatteryLevelPercentage());
DrawText(gFramebuffer, string, ArraySize(string), 0, 0, palette[3]);
}
timerRunning = false;
timerTotalMicroSecsPrePause = 0;
}
if (drawBatteryVoltage)
{
char string[10];
snprintf(string, ArraySize(string), "B: %03d", Odroid_ReadBatteryLevel());
DrawText(gFramebuffer, string, ArraySize(string), 0, 3, palette[3]);
}
bool sleepModeActivate =
currentTimeMicroSecs - timeSinceLastInputMicroSecs > autoSleepModeMicroseconds ||
(input.b && !lastFrameInput.b);
if (sleepModeActivate)
{
if (backlightOn)
// Time since boot
if (drawTimeSinceBoot)
{
// TODO: Tell LCD driver to enter sleep
// TODO: Use esp light sleep mode
Odroid_BacklightDeinit();
char string[10];
int64_t timeSinceBoot = esp_timer_get_time();
snprintf(string, ArraySize(string), "%lld", timeSinceBoot);
DrawText(gFramebuffer, string, ArraySize(string), 0, 1, palette[3]);
}
else
Odroid_BacklightInit();
backlightOn = !backlightOn;
sleepMode = !sleepMode;
}
// Frame time
if (drawFrameRate)
{
char string[10];
int64_t currentTimeMicroSecs = esp_timer_get_time();
int64_t frameTimeMicroSecs = currentTimeMicroSecs - lastFrameTimeMicroSecs;
snprintf(string, ArraySize(string), "%.2f HZ", 1000000.f / frameTimeMicroSecs);
DrawText(gFramebuffer, string, ArraySize(string), 12, 0, palette[3]);
lastFrameTimeMicroSecs = currentTimeMicroSecs;
}
// Movement
/* if (input.left) */
/* { */
/* xLeft -= 1; */
/* if (xLeft < 0) */
/* { */
/* xLeft = 39; */
/* } */
/* } */
/* else if (input.right) */
/* { */
/* xLeft += 1; */
/* if (xLeft > 39) */
/* { */
/* xLeft = 0; */
/* } */
/* } */
// Tile drawing
/* for (int tileY = 0; tileY < 15; ++tileY) */
/* { */
/* for (int tileX = xLeft; tileX < xLeft + 20; ++tileX) */
/* { */
/* int tile = tileX % 40; */
/* int tileIndex = tileBuffer[tileY][tile]; */
/* DrawTile(tileIndex, tileX - xLeft, tileY); */
/* } */
/* } */
// Battery
if (drawBatteryPercent)
{
char string[10];
snprintf(string, ArraySize(string), "B: %.0f", Odroid_ReadBatteryLevelPercentage());
DrawText(gFramebuffer, string, ArraySize(string), 0, 0, palette[3]);
}
Odroid_DrawFrame(gFramebuffer);
if (drawBatteryVoltage)
{
char string[10];
snprintf(string, ArraySize(string), "B: %03d", Odroid_ReadBatteryLevel());
DrawText(gFramebuffer, string, ArraySize(string), 0, 3, palette[3]);
}
// Just high enough that button presses feel responsive
if (enableLowFrameRate)
vTaskDelay(5);
// Time since boot
if (drawTimeSinceBoot)
{
char string[10];
int64_t timeSinceBoot = esp_timer_get_time();
snprintf(string, ArraySize(string), "%lld", timeSinceBoot);
DrawText(gFramebuffer, string, ArraySize(string), 0, 1, palette[3]);
}
lastFrameInput = input;
// Frame time
if (drawFrameRate)
{
char string[10];
int64_t currentTimeMicroSecs = esp_timer_get_time();
int64_t frameTimeMicroSecs = currentTimeMicroSecs - lastFrameTimeMicroSecs;
snprintf(string, ArraySize(string), "%.2f HZ", 1000000.f / frameTimeMicroSecs);
DrawText(gFramebuffer, string, ArraySize(string), 12, 0, palette[3]);
lastFrameTimeMicroSecs = currentTimeMicroSecs;
}
// Save screenshots for making gifs
/* if (input.menu) */
/* { */
/* snprintf(snapFilename, 20, "/sdcard/frame%02d", frameIndex); */
// Timer
{
char string[18];
int64_t currentTimeMicroSecs = esp_timer_get_time();
float timerSeconds =
timerRunning ?
((timerTotalMicroSecsPrePause + (currentTimeMicroSecs - timerStartMicroSecs)) /
1000000.f) :
timerTotalMicroSecsPrePause / 1000000.f;
snprintf(string, ArraySize(string), "%d:%.2d", (int)timerSeconds / 60,
(int)timerSeconds % 60);
DrawText(gFramebuffer, string, ArraySize(string), 3, 5, palette[3]);
if (!timerRunning)
{
snprintf(string, ArraySize(string), "Paused");
DrawText(gFramebuffer, string, ArraySize(string), 3, 6, palette[3]);
}
}
/* ESP_LOGI(LOG_TAG, "Writing snapshot to %s", snapFilename); */
// Save screenshots for making gifs
/* if (input.menu) */
/* { */
/* snprintf(snapFilename, 20, "/sdcard/frame%02d", frameIndex); */
/* FILE* snapFile = fopen(snapFilename, "wb"); */
/* assert(snapFile); */
/* ESP_LOGI(LOG_TAG, "Writing snapshot to %s", snapFilename); */
/* fwrite(gFramebuffer, 1, LCD_WIDTH * LCD_HEIGHT * sizeof(gFramebuffer[0]),
* snapFile); */
/* FILE* snapFile = fopen(snapFilename, "wb"); */
/* assert(snapFile); */
/* fclose(snapFile); */
/* fwrite(gFramebuffer, 1, LCD_WIDTH * LCD_HEIGHT * sizeof(gFramebuffer[0]), snapFile); */
/* ++frameIndex; */
/* } */
}
/* fclose(snapFile); */
if (state == Sleeping)
{
// Enter sleep
{
// TODO: Tell LCD driver to enter sleep
Odroid_BacklightDeinit();
}
/* ++frameIndex; */
/* } */
// Try to save battery while still listening to inputs
// This loop is exited only if wake button is pressed
while (!Odroid_EnterLightSleep(lightSleepMicroseconds))
{
updateBatteryIndicator();
}
Odroid_DrawFrame(gFramebuffer);
// Exit sleep
{
// Count this input so sleep isn't immediately entered
timeSinceLastInputMicroSecs = esp_timer_get_time();
// Just high enough that button presses feel responsive
if (enableLowFrameRate)
vTaskDelay(5);
Odroid_BacklightInit();
lastFrameInput = input;
state = Awake_WaitingForWakeButtonRelease;
}
}
}
// Should never get here

16
app/src/odroid/input.c

@ -7,14 +7,14 @@
static const char* LOG_TAG = "OdroidInput";
static const gpio_num_t BUTTON_PIN_A = GPIO_NUM_32;
static const gpio_num_t BUTTON_PIN_B = GPIO_NUM_33;
static const gpio_num_t BUTTON_PIN_START = GPIO_NUM_39;
static const gpio_num_t BUTTON_PIN_SELECT = GPIO_NUM_27;
static const gpio_num_t BUTTON_PIN_VOLUME = GPIO_NUM_0;
static const gpio_num_t BUTTON_PIN_MENU = GPIO_NUM_13;
static const adc1_channel_t DPAD_PIN_X_AXIS = ADC1_GPIO34_CHANNEL;
static const adc1_channel_t DPAD_PIN_Y_AXIS = ADC1_GPIO35_CHANNEL;
const gpio_num_t BUTTON_PIN_A = GPIO_NUM_32;
const gpio_num_t BUTTON_PIN_B = GPIO_NUM_33;
const gpio_num_t BUTTON_PIN_START = GPIO_NUM_39;
const gpio_num_t BUTTON_PIN_SELECT = GPIO_NUM_27;
const gpio_num_t BUTTON_PIN_VOLUME = GPIO_NUM_0;
const gpio_num_t BUTTON_PIN_MENU = GPIO_NUM_13;
const adc1_channel_t DPAD_PIN_X_AXIS = ADC1_GPIO34_CHANNEL;
const adc1_channel_t DPAD_PIN_Y_AXIS = ADC1_GPIO35_CHANNEL;
void Odroid_InitializeInput()

11
app/src/odroid/input.h

@ -2,6 +2,8 @@
#include <stdint.h>
#include <driver/gpio.h>
#include <driver/adc.h>
typedef struct
{
@ -21,3 +23,12 @@ void Odroid_InitializeInput(void);
Odroid_Input Odroid_PollInput(void);
void Odroid_PrintInputState(Odroid_Input* input);
int Odroid_HasAnyInput(Odroid_Input* input);
extern const gpio_num_t BUTTON_PIN_A;
extern const gpio_num_t BUTTON_PIN_B;
extern const gpio_num_t BUTTON_PIN_START;
extern const gpio_num_t BUTTON_PIN_SELECT;
extern const gpio_num_t BUTTON_PIN_VOLUME;
extern const gpio_num_t BUTTON_PIN_MENU;
extern const adc1_channel_t DPAD_PIN_X_AXIS;
extern const adc1_channel_t DPAD_PIN_Y_AXIS;

57
app/src/odroid/sleep.c

@ -10,9 +10,9 @@
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
// Button B
#define BUTTON_GPIO_NUM_DEFAULT GPIO_NUM_32
#define BUTTON_WAKEUP_LEVEL_DEFAULT 1
#include "input.h"
#define BUTTON_WAKEUP_LEVEL_DEFAULT 0
// Returns whether button was pressed to wake
// See Dependencies/esp-idf/examples/system/light_sleep/main/light_sleep_example_main.c
@ -20,12 +20,22 @@ bool Odroid_EnterLightSleep(int64_t timerAutoWakeupMicroSecs)
{
esp_sleep_enable_timer_wakeup(timerAutoWakeupMicroSecs);
const int button_gpio_num = BUTTON_GPIO_NUM_DEFAULT;
const int wakeup_level = BUTTON_WAKEUP_LEVEL_DEFAULT;
gpio_config_t config = {.pin_bit_mask = BIT64(button_gpio_num), .mode = GPIO_MODE_INPUT};
gpio_config_t config = {.pin_bit_mask = (1ULL << BUTTON_PIN_A) | (1ULL << BUTTON_PIN_B) |
(1ULL << BUTTON_PIN_START) |
(1ULL << BUTTON_PIN_SELECT) |
(1ULL << BUTTON_PIN_VOLUME) | (1ULL << BUTTON_PIN_MENU),
.mode = GPIO_MODE_INPUT,
.pull_up_en = GPIO_PULLUP_ENABLE};
ESP_ERROR_CHECK(gpio_config(&config));
gpio_wakeup_enable(button_gpio_num,
wakeup_level == 0 ? GPIO_INTR_LOW_LEVEL : GPIO_INTR_HIGH_LEVEL);
gpio_num_t buttonsToWatch[] = {BUTTON_PIN_A, BUTTON_PIN_B, BUTTON_PIN_START,
BUTTON_PIN_SELECT, BUTTON_PIN_VOLUME, BUTTON_PIN_MENU};
for (int i = 0; i < sizeof(buttonsToWatch) / sizeof(buttonsToWatch[0]); ++i)
{
gpio_wakeup_enable(buttonsToWatch[i],
wakeup_level == 0 ? GPIO_INTR_LOW_LEVEL : GPIO_INTR_HIGH_LEVEL);
}
esp_sleep_enable_gpio_wakeup();
printf("Entering light sleep\n");
@ -49,8 +59,31 @@ bool Odroid_EnterLightSleep(int64_t timerAutoWakeupMicroSecs)
case ESP_SLEEP_WAKEUP_TIMER:
wakeup_reason = "timer";
break;
case ESP_SLEEP_WAKEUP_UNDEFINED:
wakeup_reason = "undefined";
break;
case ESP_SLEEP_WAKEUP_ALL:
wakeup_reason =
"Not a wakeup cause, used to disable all wakeup sources with "
"esp_sleep_disable_wakeup_source.";
break;
case ESP_SLEEP_WAKEUP_EXT0:
wakeup_reason = "external signal using RTC_IO.";
break;
case ESP_SLEEP_WAKEUP_EXT1:
wakeup_reason = "external signal using RTC_CNTL.";
break;
case ESP_SLEEP_WAKEUP_TOUCHPAD:
wakeup_reason = "touchpad";
break;
case ESP_SLEEP_WAKEUP_ULP:
wakeup_reason = "ULP program";
break;
case ESP_SLEEP_WAKEUP_GPIO:
wakeup_reason = "pin";
wakeup_reason = "GPIO (light sleep only)";
break;
case ESP_SLEEP_WAKEUP_UART:
wakeup_reason = "UART (light sleep only)";
break;
default:
wakeup_reason = "other";
@ -60,5 +93,13 @@ bool Odroid_EnterLightSleep(int64_t timerAutoWakeupMicroSecs)
printf("Returned from light sleep, reason: %s, t=%lld ms, slept for %lld ms\n", wakeup_reason,
t_after_us / 1000, (t_after_us - t_before_us) / 1000);
for (int i = 0; i < sizeof(buttonsToWatch) / sizeof(buttonsToWatch[0]); ++i)
{
gpio_wakeup_disable(buttonsToWatch[i]);
}
/// Reconfigure GPIO to our desired settings
Odroid_InitializeInput();
return cause == ESP_SLEEP_WAKEUP_GPIO;
}

Loading…
Cancel
Save