GameCounter/Source/src/screen/counter.c

189 lines
3.9 KiB
C

#include "counter.h"
#include <stdint.h>
#include <ssd1306xled.h>
#include "state.h"
#include "../buttons.h"
#include "../power.h"
#define CounterMinValue -99
#define CounterMaxValue 999
int16_t lastDrawnCounter = 9999;
int16_t counter = 0;
// Forward declarations
void drawCounter();
void drawDigit(uint8_t* column, uint8_t digit);
void drawMinusSign(uint8_t* column);
void blankDigitColumn(uint8_t* column, uint8_t width);
void handleCounterScreen()
{
if (button_is_pressed_short(&buttonOption))
{
// Turn off power to the screen
if (powerState == On)
setPowerState(ManualOff);
return;
}
if (button_is_pressed_long(&buttonOption))
{
setCurrentScreen(Menu);
return;
}
if (button_is_pressed_or_repeated(&buttonUp))
{
if (counter < CounterMaxValue)
counter++;
}
else if (button_is_pressed_or_repeated(&buttonDown))
{
if (counter > CounterMinValue)
counter--;
}
uint8_t invalidated = getScreenInvalidated();
if (counter != lastDrawnCounter || invalidated)
{
if (invalidated)
ssd1306_clear();
drawCounter();
lastDrawnCounter = counter;
}
}
void resetCounter()
{
counter = 0;
}
void drawCounter()
{
uint8_t column = DigitFullOffset;
if (counter < -9)
{
// Two digit negative, blank left and right (minimizes flicker) and spacing
blankDigitColumn(&column, SpacingNegativeLeft2);
drawMinusSign(&column);
blankDigitColumn(&column, DigitSpacing);
drawDigit(&column, (-counter) / 10);
blankDigitColumn(&column, DigitSpacing);
drawDigit(&column, (-counter) % 10);
blankDigitColumn(&column, SpacingNegativeRight2);
}
else if (counter < 0)
{
// Single digit negative, similar
blankDigitColumn(&column, SpacingNegativeLeft1);
drawMinusSign(&column);
blankDigitColumn(&column, DigitSpacing);
drawDigit(&column, -counter);
blankDigitColumn(&column, SpacingNegativeRight1);
}
else if (counter < 10)
{
// Single digit, blank left and right only
blankDigitColumn(&column, SpacingLeft1);
drawDigit(&column, counter);
blankDigitColumn(&column, SpacingRight1);
}
else if (counter < 100)
{
// Two digits, you know the drill by now
blankDigitColumn(&column, SpacingLeft2);
drawDigit(&column, counter / 10);
blankDigitColumn(&column, DigitSpacing);
drawDigit(&column, counter % 10);
blankDigitColumn(&column, SpacingRight2);
}
else
{
// Three digits
drawDigit(&column, counter / 100);
blankDigitColumn(&column, DigitSpacing);
drawDigit(&column, (counter % 100) / 10);
blankDigitColumn(&column, DigitSpacing);
drawDigit(&column, counter % 10);
}
}
void drawDigit(uint8_t* column, uint8_t digit)
{
if (digit > 9) return;
uint8_t yEnd = DigitPage + DigitRows;
uint16_t bitmapOffset = digit * DigitBytesPerChar;
for (uint8_t y = DigitPage; y < yEnd; y++)
{
ssd1306_setpos(*column, y);
ssd1306_send_data_start();
for (uint8_t x = 0; x < DigitWidth; x++)
{
ssd1306_send_byte(pgm_read_byte(&Digits[bitmapOffset]));
bitmapOffset++;
}
ssd1306_send_data_stop();
}
(*column) += DigitWidth;
}
void drawMinusSign(uint8_t* column)
{
uint8_t yEnd = DigitPage + DigitRows;
uint16_t bitmapOffset = 0;
for (uint8_t y = DigitPage; y < yEnd; y++)
{
ssd1306_setpos(*column, y);
ssd1306_send_data_start();
for (uint8_t x = 0; x < MinusSignWidth; x++)
{
ssd1306_send_byte(pgm_read_byte(&MinusSign[bitmapOffset]));
bitmapOffset++;
}
ssd1306_send_data_stop();
}
(*column) += MinusSignWidth;
}
void blankDigitColumn(uint8_t* column, uint8_t width)
{
uint8_t yEnd = DigitPage + DigitRows;
for (uint8_t y = DigitPage; y < yEnd; y++)
{
ssd1306_setpos(*column, y);
ssd1306_send_data_start();
for (uint8_t i = 0; i < width; i++)
ssd1306_send_byte(0);
ssd1306_send_data_stop();
}
(*column) += width;
}