aboutsummaryrefslogtreecommitdiffhomepage
path: root/source/Core/Drivers/BootLogo.cpp
blob: af43fee435eca741477a37a3a9905485ff2b166e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
#include "BootLogo.h"
#include "BSP.h"
#include "Buttons.hpp"
#include "OLED.hpp"
#include "Settings.h"
#include "cmsis_os.h"

#define LOGO_PAGE_LENGTH 1024

void delay() {
  if (getSettingValue(SettingsOptions::LOGOTime) >= logoMode_t::ONETIME) {
    waitForButtonPress();
  } else {
    waitForButtonPressOrTimeout(TICKS_SECOND * getSettingValue(SettingsOptions::LOGOTime));
  }
}

void BootLogo::handleShowingLogo(const uint8_t *ptrLogoArea) {
  OLED::clearScreen();
  // Read the first few bytes and figure out what format we are looking at
  if (OLD_LOGO_HEADER_VALUE == *(reinterpret_cast<const uint32_t *>(ptrLogoArea))) {
    showOldFormat(ptrLogoArea);
  } else if (ptrLogoArea[0] == 0xAA) {
    showNewFormat(ptrLogoArea + 1);
  }

  OLED::clearScreen();
}

void BootLogo::showOldFormat(const uint8_t *ptrLogoArea) {
#ifdef OLED_128x32
  // Draw in middle
  OLED::drawAreaSwapped(16, 8, 96, 16, (uint8_t *)(ptrLogoArea + 4));

#else
  OLED::drawAreaSwapped(0, 0, 96, 16, (uint8_t *)(ptrLogoArea + 4));

#endif
  OLED::refresh();
  // Delay here with static logo until a button is pressed or its been the amount of seconds set by the user
  delay();
}

void BootLogo::showNewFormat(const uint8_t *ptrLogoArea) {
  if (getSettingValue(SettingsOptions::LOGOTime) == logoMode_t::SKIP) {
    return;
  }

  // New logo format (a) fixes long standing byte swap quirk and (b) supports animation
  uint8_t interFrameDelay = ptrLogoArea[0];
  OLED::clearScreen();

  // Now draw in the frames
  int position = 1;
  while (getButtonState() == BUTTON_NONE) {
    int len = (showNewFrame(ptrLogoArea + position));
    OLED::refresh();
    position += len;

    if (interFrameDelay) {
      osDelay(interFrameDelay * 4);
    }

    // 1024 less the header type byte and the inter-frame-delay
    if (getSettingValue(SettingsOptions::LOGOTime) && (position >= 1022 || len == 0)) {
      // Animated logo stops here ...
      if (getSettingValue(SettingsOptions::LOGOTime) == logoMode_t::INFINITY) {
        // ... but if it's infinite logo setting then keep it rolling over again until a button is pressed
        osDelay(4 * TICKS_100MS);
        OLED::clearScreen();
        position = 1;
        continue;
      }
    } else {
      // Animation in progress so jumping to the next frame
      continue;
    }

    // Static logo case ends up right here, so delay until a button is pressed or its been the amount of seconds set by the user
    delay();
    return;
  }
}

int BootLogo::showNewFrame(const uint8_t *ptrLogoArea) {
  uint8_t length = ptrLogoArea[0];
  switch (length) {
  case 0:
    // End
    return 0;
    break;
  case 0xFE:
    return 1;
    break;
  case 0xFF:
// Full frame update
#ifdef OLED_128x32
    OLED::drawArea(16, 8, 96, 16, ptrLogoArea + 1);
#else
    OLED::drawArea(0, 0, 96, 16, ptrLogoArea + 1);
#endif
    length = 96;
    break;
  default:
    length /= 2;
    // Draw length patches
    for (int p = 0; p < length; p++) {
      uint8_t index = ptrLogoArea[1 + (p * 2)];
      uint8_t value = ptrLogoArea[2 + (p * 2)];
#ifdef OLED_128x32
      OLED::drawArea(16 + (index % 96), index >= 96 ? 16 : 8, 1, 8, &value);
#else
      OLED::drawArea(index % 96, index >= 96 ? 8 : 0, 1, 8, &value);
#endif
    }
  }

  OLED::refresh();
  return (length * 2) + 1;
}