Remove unused files and graphics app.

Factory loader : display InfiniTime logo & progress bar.
This commit is contained in:
JF 2020-12-06 20:57:55 +01:00
parent a7484e6daa
commit 9ae0550a84
9 changed files with 615 additions and 13839 deletions

File diff suppressed because it is too large Load Diff

View File

@ -425,24 +425,6 @@ list(APPEND FACTORY_SOURCE_FILES
)
list(APPEND GRAPHICS_SOURCE_FILES
# FreeRTOS
FreeRTOS/port.c
FreeRTOS/port_cmsis_systick.c
FreeRTOS/port_cmsis.c
drivers/SpiNorFlash.cpp
drivers/SpiMaster.cpp
drivers/Spi.cpp
logging/NrfLogger.cpp
components/gfx/Gfx.cpp
drivers/St7789.cpp
components/brightness/BrightnessController.cpp
graphics.cpp
)
list(APPEND FACTORYLOADER_SOURCE_FILES
# FreeRTOS
FreeRTOS/port.c
@ -454,10 +436,13 @@ list(APPEND FACTORYLOADER_SOURCE_FILES
drivers/Spi.cpp
logging/NrfLogger.cpp
components/rle/RleDecoder.cpp
components/gfx/Gfx.cpp
drivers/St7789.cpp
components/brightness/BrightnessController.cpp
displayapp/icons/infinitime/infinitime-nb.c
factory.cpp
)
@ -736,35 +721,6 @@ add_custom_command(TARGET ${EXECUTABLE_MCUBOOT_NAME}
COMMENT "post build steps for ${EXECUTABLE_MCUBOOT_FILE_NAME}"
)
# Build binary that writes the graphic assets for the bootloader
set(EXECUTABLE_GRAPHICS_NAME "pinetime-graphics")
set(EXECUTABLE_GRAPHICS_FILE_NAME ${EXECUTABLE_GRAPHICS_NAME}-${pinetime_VERSION_MAJOR}.${pinetime_VERSION_MINOR}.${pinetime_VERSION_PATCH})
add_executable(${EXECUTABLE_GRAPHICS_NAME} ${GRAPHICS_SOURCE_FILES})
target_link_libraries(${EXECUTABLE_GRAPHICS_NAME} nrf-sdk)
set_target_properties(${EXECUTABLE_GRAPHICS_NAME} PROPERTIES OUTPUT_NAME ${EXECUTABLE_GRAPHICS_FILE_NAME})
target_compile_options(${EXECUTABLE_GRAPHICS_NAME} PUBLIC
$<$<AND:$<COMPILE_LANGUAGE:C>,$<CONFIG:DEBUG>>: ${COMMON_FLAGS} -O0 -g3>
$<$<AND:$<COMPILE_LANGUAGE:C>,$<CONFIG:RELEASE>>: ${COMMON_FLAGS} -O3>
$<$<AND:$<COMPILE_LANGUAGE:CXX>,$<CONFIG:DEBUG>>: ${COMMON_FLAGS} -O0 -g3>
$<$<AND:$<COMPILE_LANGUAGE:CXX>,$<CONFIG:RELEASE>>: ${COMMON_FLAGS} -O3>
$<$<COMPILE_LANGUAGE:ASM>: -MP -MD -std=c99 -x assembler-with-cpp>
)
set_target_properties(${EXECUTABLE_GRAPHICS_NAME} PROPERTIES
SUFFIX ".out"
LINK_FLAGS "-mthumb -mabi=aapcs -std=gnu++98 -std=c99 -L ${NRF5_SDK_PATH}/modules/nrfx/mdk -T${NRF5_LINKER_SCRIPT} -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=fpv4-sp-d16 -Wl,--gc-sections --specs=nano.specs -lc -lnosys -lm -Wl,-Map=${EXECUTABLE_GRAPHICS_FILE_NAME}.map"
CXX_STANDARD 11
C_STANDARD 99
)
add_custom_command(TARGET ${EXECUTABLE_GRAPHICS_NAME}
POST_BUILD
COMMAND ${CMAKE_SIZE_UTIL} ${EXECUTABLE_GRAPHICS_FILE_NAME}.out
COMMAND ${CMAKE_OBJCOPY} -O binary ${EXECUTABLE_GRAPHICS_FILE_NAME}.out "${EXECUTABLE_GRAPHICS_FILE_NAME}.bin"
COMMAND ${CMAKE_OBJCOPY} -O ihex ${EXECUTABLE_GRAPHICS_FILE_NAME}.out "${EXECUTABLE_GRAPHICS_FILE_NAME}.hex"
COMMENT "post build steps for ${EXECUTABLE_GRAPHICS_FILE_NAME}"
)
# infinitime-light
set(EXECUTABLE_FACTORY_NAME "pinetime-factory")
set(EXECUTABLE_FACTORY_FILE_NAME ${EXECUTABLE_FACTORY_NAME}-${pinetime_VERSION_MAJOR}.${pinetime_VERSION_MINOR}.${pinetime_VERSION_PATCH})

View File

@ -0,0 +1,32 @@
#include "RleDecoder.h"
using namespace Pinetime::Tools;
RleDecoder::RleDecoder(const uint8_t *buffer, size_t size) : buffer{buffer}, size{size} {
}
void RleDecoder::DecodeNext(uint8_t *output, size_t maxBytes) {
for (;encodedBufferIndex<size; encodedBufferIndex++) {
uint8_t rl = buffer[encodedBufferIndex] - processedCount;
while (rl) {
output[bp] = color >> 8;
output[bp + 1] = color & 0xff;
bp += 2;
rl -= 1;
processedCount++;
if (bp >= maxBytes) {
bp = 0;
y += 1;
return;
}
}
processedCount = 0;
if (color == backgroundColor)
color = foregroundColor;
else
color = backgroundColor;
}
}

View File

@ -0,0 +1,32 @@
#pragma once
#include <cstdint>
#include <cstddef>
namespace Pinetime {
namespace Tools {
/* 1-bit RLE decoder. Provide the encoded buffer to the constructor and then call DecodeNext() by
* specifying the output (decoded) buffer and the maximum number of bytes this buffer can handle.
*
* Code from https://github.com/daniel-thompson/wasp-bootloader by Daniel Thompson released under the MIT license.
*/
class RleDecoder {
public:
RleDecoder(const uint8_t* buffer, size_t size);
void DecodeNext(uint8_t* output, size_t maxBytes);
private:
const uint8_t* buffer;
size_t size;
int encodedBufferIndex = 0;
int y = 0;
uint16_t bp = 0;
static constexpr uint16_t foregroundColor = 0xffff;
static constexpr uint16_t backgroundColor = 0;
uint16_t color = backgroundColor;
int processedCount = 0;
};
}
}

View File

@ -0,0 +1,127 @@
#include <unistd.h>
// 1-bit RLE, generated from ./infinitime-nb.png, 1445 bytes
static const uint8_t infinitime_nb[] = {
0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0,
0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0,
0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0x66, 0x2, 0xed, 0x4, 0xec, 0x5,
0xea, 0x7, 0xe8, 0x9, 0xe6, 0xa, 0xe5, 0xc, 0xe3, 0xe, 0xe1, 0x10,
0xdf, 0x12, 0xde, 0x12, 0xdd, 0x14, 0xdb, 0x16, 0xd9, 0x18, 0xd7, 0x1a,
0xd5, 0x1b, 0xd4, 0x1d, 0xd3, 0xd, 0x3, 0xe, 0xd1, 0xd, 0x5, 0xe,
0xcf, 0xe, 0x5, 0xf, 0xcd, 0xf, 0x5, 0xf, 0xcc, 0x10, 0x5, 0x10,
0xca, 0x11, 0x5, 0x11, 0xc8, 0x12, 0x5, 0x12, 0xc6, 0x13, 0x5, 0x13,
0xc5, 0x13, 0x5, 0x13, 0xc4, 0x14, 0x5, 0x14, 0xc2, 0x15, 0x5, 0x15,
0xc0, 0x17, 0x3, 0x17, 0xbe, 0x33, 0xbc, 0x34, 0xbb, 0x36, 0xba, 0x37,
0xb8, 0x39, 0xb6, 0x3b, 0xb4, 0x3c, 0xb3, 0x3e, 0xb1, 0x40, 0xaf, 0x9,
0x2, 0x2e, 0x1, 0x8, 0xad, 0x9, 0x4, 0x2c, 0x3, 0x8, 0xac, 0x8,
0x6, 0x2a, 0x5, 0x7, 0xab, 0x9, 0x6, 0x29, 0x6, 0x8, 0xa9, 0xb,
0x5, 0x29, 0x5, 0xa, 0xa7, 0xd, 0x3, 0x2b, 0x3, 0xc, 0xa5, 0x4c,
0xa3, 0x4d, 0xa2, 0x4f, 0xa0, 0x51, 0x9f, 0x52, 0x9d, 0x54, 0x9b, 0x55,
0x9a, 0x57, 0x98, 0x59, 0x96, 0x5b, 0x94, 0x5d, 0x93, 0x5d, 0x92, 0x5f,
0x90, 0x61, 0x8e, 0x63, 0x8c, 0x65, 0x8a, 0x66, 0x89, 0x68, 0x87, 0x8,
0x2, 0x59, 0x2, 0x5, 0x86, 0x7, 0x4, 0x57, 0x4, 0x5, 0x84, 0x8,
0x5, 0x55, 0x6, 0x5, 0x82, 0x9, 0x6, 0x54, 0x6, 0x5, 0x81, 0xa,
0x5, 0x55, 0x5, 0x7, 0x7f, 0xc, 0x4, 0x56, 0x3, 0x9, 0x7d, 0x74,
0x7b, 0x76, 0x79, 0x77, 0x79, 0x78, 0x77, 0x7a, 0x75, 0x7c, 0x73, 0x7e,
0x71, 0x7f, 0x70, 0x81, 0x6e, 0x83, 0x6c, 0x85, 0x6b, 0x86, 0x69, 0x87,
0x68, 0x89, 0x66, 0x8b, 0x64, 0x8d, 0x62, 0x8f, 0x60, 0x90, 0x60, 0x91,
0x5e, 0x93, 0x5c, 0x95, 0x5a, 0xe, 0x7, 0x71, 0x7, 0xa, 0x58, 0xd,
0xb, 0x6d, 0xb, 0x8, 0x57, 0xe, 0xc, 0x6c, 0xc, 0x8, 0x55, 0xf,
0xc, 0x6c, 0xb, 0xa, 0x53, 0x11, 0xa, 0x6d, 0xb, 0xb, 0x52, 0x9f,
0x50, 0xa0, 0x4f, 0xa2, 0x4d, 0xa4, 0x4b, 0xa6, 0x49, 0xa8, 0x48, 0xa8,
0xff, 0x0, 0xe3, 0x44, 0xad, 0x43, 0xae, 0x41, 0xb0, 0x40, 0xb1, 0x3e,
0xb2, 0x3e, 0xb3, 0x3c, 0xb5, 0x3a, 0xb7, 0x39, 0xb8, 0x37, 0xb9, 0x36,
0xbb, 0x35, 0xe, 0x1, 0x66, 0x1, 0x3c, 0x1, 0x9, 0x33, 0xe, 0x3,
0x15, 0x5, 0xe, 0x4, 0x16, 0x15, 0xd, 0x3, 0x11, 0x5, 0xe, 0x4,
0x12, 0x3, 0x9, 0x31, 0xf, 0x4, 0x14, 0x6, 0xd, 0x4, 0x16, 0x15,
0xd, 0x4, 0x10, 0x5, 0xe, 0x4, 0x12, 0x4, 0x9, 0x30, 0xf, 0x4,
0x14, 0x6, 0xd, 0x4, 0x16, 0x15, 0xd, 0x4, 0x10, 0x6, 0xd, 0x4,
0x12, 0x4, 0x9, 0x2f, 0x10, 0x4, 0x14, 0x7, 0xc, 0x4, 0x16, 0x15,
0xd, 0x4, 0x10, 0x6, 0xd, 0x4, 0x12, 0x4, 0xa, 0x2d, 0x11, 0x4,
0x14, 0x7, 0xc, 0x4, 0x16, 0x4, 0x1e, 0x4, 0x10, 0x7, 0xc, 0x4,
0x12, 0x4, 0xb, 0x2c, 0x11, 0x4, 0x14, 0x8, 0xb, 0x4, 0x16, 0x4,
0x1e, 0x4, 0x10, 0x7, 0xc, 0x4, 0x12, 0x4, 0xc, 0x2a, 0x12, 0x4,
0x14, 0x8, 0xb, 0x4, 0x16, 0x4, 0x1e, 0x4, 0x10, 0x8, 0xb, 0x4,
0x12, 0x4, 0xd, 0x28, 0x13, 0x4, 0x14, 0x4, 0x1, 0x4, 0xa, 0x4,
0x16, 0x4, 0x1e, 0x4, 0x10, 0x4, 0x1, 0x3, 0xb, 0x4, 0x12, 0x4,
0xd, 0x28, 0x13, 0x4, 0x14, 0x4, 0x1, 0x4, 0xa, 0x4, 0x16, 0x4,
0x1e, 0x4, 0x10, 0x4, 0x1, 0x4, 0xa, 0x4, 0x12, 0x4, 0xe, 0x26,
0x14, 0x4, 0x14, 0x4, 0x2, 0x4, 0x9, 0x4, 0x16, 0x4, 0x1e, 0x4,
0x10, 0x4, 0x2, 0x3, 0xa, 0x4, 0x12, 0x4, 0xf, 0x24, 0x15, 0x4,
0x14, 0x4, 0x2, 0x4, 0x9, 0x4, 0x16, 0x4, 0x1e, 0x4, 0x10, 0x4,
0x2, 0x4, 0x9, 0x4, 0x12, 0x4, 0x10, 0x23, 0x15, 0x4, 0x14, 0x4,
0x3, 0x4, 0x8, 0x4, 0x16, 0x4, 0x1e, 0x4, 0x10, 0x4, 0x2, 0x4,
0x9, 0x4, 0x12, 0x4, 0x11, 0x21, 0x16, 0x4, 0x14, 0x4, 0x3, 0x4,
0x8, 0x4, 0x16, 0x4, 0x1e, 0x4, 0x10, 0x4, 0x3, 0x4, 0x8, 0x4,
0x12, 0x4, 0x11, 0x20, 0x17, 0x4, 0x14, 0x4, 0x4, 0x3, 0x8, 0x4,
0x16, 0x4, 0x1e, 0x4, 0x10, 0x4, 0x3, 0x4, 0x8, 0x4, 0x12, 0x4,
0x12, 0x1f, 0x17, 0x4, 0x14, 0x4, 0x4, 0x4, 0x7, 0x4, 0x16, 0x4,
0x1e, 0x4, 0x10, 0x4, 0x4, 0x3, 0x8, 0x4, 0x12, 0x4, 0x13, 0x1d,
0x18, 0x4, 0x14, 0x4, 0x5, 0x3, 0x7, 0x4, 0x16, 0x13, 0xf, 0x4,
0x10, 0x4, 0x4, 0x4, 0x7, 0x4, 0x12, 0x4, 0x14, 0x1b, 0x1a, 0x3,
0x14, 0x4, 0x5, 0x4, 0x6, 0x4, 0x16, 0x13, 0x10, 0x3, 0x10, 0x4,
0x5, 0x3, 0x7, 0x4, 0x13, 0x3, 0x15, 0x1a, 0x1b, 0x1, 0x15, 0x4,
0x6, 0x3, 0x6, 0x4, 0x16, 0x13, 0x11, 0x1, 0x11, 0x4, 0x5, 0x4,
0x6, 0x4, 0x14, 0x1, 0x16, 0x19, 0x32, 0x4, 0x6, 0x4, 0x5, 0x4,
0x16, 0x13, 0x23, 0x4, 0x6, 0x3, 0x6, 0x4, 0x2c, 0x17, 0x33, 0x4,
0x7, 0x3, 0x5, 0x4, 0x16, 0x4, 0x32, 0x4, 0x6, 0x4, 0x5, 0x4,
0x2d, 0x16, 0x1d, 0x1, 0x15, 0x4, 0x7, 0x4, 0x4, 0x4, 0x16, 0x4,
0x20, 0x1, 0x11, 0x4, 0x7, 0x3, 0x5, 0x4, 0x14, 0x1, 0x19, 0x14,
0x1d, 0x3, 0x14, 0x4, 0x7, 0x4, 0x4, 0x4, 0x16, 0x4, 0x1f, 0x3,
0x10, 0x4, 0x7, 0x4, 0x4, 0x4, 0x13, 0x3, 0x19, 0x12, 0x1d, 0x4,
0x14, 0x4, 0x8, 0x4, 0x3, 0x4, 0x16, 0x4, 0x1e, 0x4, 0x10, 0x4,
0x8, 0x3, 0x4, 0x4, 0x12, 0x4, 0x19, 0x12, 0x1d, 0x4, 0x14, 0x4,
0x8, 0x4, 0x3, 0x4, 0x16, 0x4, 0x1e, 0x4, 0x10, 0x4, 0x8, 0x4,
0x3, 0x4, 0x12, 0x4, 0x1a, 0x10, 0x1e, 0x4, 0x14, 0x4, 0x9, 0x3,
0x3, 0x4, 0x16, 0x4, 0x1e, 0x4, 0x10, 0x4, 0x8, 0x4, 0x3, 0x4,
0x12, 0x4, 0x1b, 0xe, 0x1f, 0x4, 0x14, 0x4, 0x9, 0x4, 0x2, 0x4,
0x16, 0x4, 0x1e, 0x4, 0x10, 0x4, 0x9, 0x4, 0x2, 0x4, 0x12, 0x4,
0x1c, 0xd, 0x1f, 0x4, 0x14, 0x4, 0xa, 0x3, 0x2, 0x4, 0x16, 0x4,
0x1e, 0x4, 0x10, 0x4, 0x9, 0x4, 0x2, 0x4, 0x12, 0x4, 0x1d, 0xb,
0x20, 0x4, 0x14, 0x4, 0xa, 0x4, 0x1, 0x4, 0x16, 0x4, 0x1e, 0x4,
0x10, 0x4, 0xa, 0x3, 0x2, 0x4, 0x12, 0x4, 0x1d, 0xb, 0x20, 0x4,
0x14, 0x4, 0xb, 0x3, 0x1, 0x4, 0x16, 0x4, 0x1e, 0x4, 0x10, 0x4,
0xa, 0x4, 0x1, 0x4, 0x12, 0x4, 0x1e, 0x9, 0x21, 0x4, 0x14, 0x4,
0xb, 0x8, 0x16, 0x4, 0x1e, 0x4, 0x10, 0x4, 0xb, 0x3, 0x1, 0x4,
0x12, 0x4, 0x1f, 0x7, 0x22, 0x4, 0x14, 0x4, 0xc, 0x7, 0x16, 0x4,
0x1e, 0x4, 0x10, 0x4, 0xb, 0x8, 0x12, 0x4, 0x20, 0x6, 0x22, 0x4,
0x14, 0x4, 0xc, 0x7, 0x16, 0x4, 0x1e, 0x4, 0x10, 0x4, 0xc, 0x7,
0x12, 0x4, 0x21, 0x4, 0x23, 0x4, 0x14, 0x4, 0xd, 0x6, 0x16, 0x4,
0x1e, 0x4, 0x10, 0x4, 0xc, 0x7, 0x12, 0x4, 0x21, 0x3, 0x24, 0x4,
0x14, 0x4, 0xd, 0x6, 0x16, 0x4, 0x1e, 0x4, 0x10, 0x4, 0xd, 0x6,
0x12, 0x4, 0x22, 0x2, 0x24, 0x4, 0x14, 0x4, 0xd, 0x6, 0x16, 0x4,
0x1e, 0x4, 0x10, 0x4, 0xd, 0x6, 0x12, 0x4, 0x48, 0x3, 0x15, 0x4,
0xe, 0x5, 0x16, 0x4, 0x1e, 0x3, 0x11, 0x4, 0xd, 0x6, 0x12, 0x3,
0x4a, 0x1, 0x66, 0x1, 0x3c, 0x1, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0,
0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0x10, 0x11,
0xf, 0x9, 0xf, 0x4, 0x9, 0x4, 0xd, 0xf, 0x8b, 0x11, 0xf, 0x9,
0xf, 0x5, 0x7, 0x5, 0xd, 0xf, 0x8b, 0x11, 0xf, 0x9, 0xf, 0x5,
0x7, 0x5, 0xd, 0xf, 0x92, 0x3, 0x19, 0x3, 0x12, 0x6, 0x5, 0x6,
0xd, 0x3, 0x9e, 0x3, 0x19, 0x3, 0x12, 0x6, 0x5, 0x6, 0xd, 0x3,
0x9e, 0x3, 0x19, 0x3, 0x12, 0x6, 0x5, 0x6, 0xd, 0x3, 0x9e, 0x3,
0x19, 0x3, 0x12, 0x3, 0x1, 0x3, 0x3, 0x3, 0x1, 0x3, 0xd, 0x3,
0x9e, 0x3, 0x19, 0x3, 0x12, 0x3, 0x2, 0x2, 0x3, 0x2, 0x2, 0x3,
0xd, 0x3, 0x9e, 0x3, 0x19, 0x3, 0x12, 0x3, 0x2, 0x3, 0x1, 0x3,
0x2, 0x3, 0xd, 0x3, 0x9e, 0x3, 0x19, 0x3, 0x12, 0x3, 0x2, 0x3,
0x1, 0x3, 0x2, 0x3, 0xd, 0x3, 0x9e, 0x3, 0x19, 0x3, 0x12, 0x3,
0x3, 0x5, 0x3, 0x3, 0xd, 0xd, 0x94, 0x3, 0x19, 0x3, 0x12, 0x3,
0x3, 0x5, 0x3, 0x3, 0xd, 0xd, 0x94, 0x3, 0x19, 0x3, 0x12, 0x3,
0x4, 0x3, 0x4, 0x3, 0xd, 0xd, 0x94, 0x3, 0x19, 0x3, 0x12, 0x3,
0x4, 0x3, 0x4, 0x3, 0xd, 0x3, 0x9e, 0x3, 0x19, 0x3, 0x12, 0x3,
0x5, 0x1, 0x5, 0x3, 0xd, 0x3, 0x9e, 0x3, 0x19, 0x3, 0x12, 0x3,
0x5, 0x1, 0x5, 0x3, 0xd, 0x3, 0x9e, 0x3, 0x19, 0x3, 0x12, 0x3,
0xb, 0x3, 0xd, 0x3, 0x9e, 0x3, 0x19, 0x3, 0x12, 0x3, 0xb, 0x3,
0xd, 0x3, 0x9e, 0x3, 0x19, 0x3, 0x12, 0x3, 0xb, 0x3, 0xd, 0x3,
0x9e, 0x3, 0x19, 0x3, 0x12, 0x3, 0xb, 0x3, 0xd, 0x3, 0x9e, 0x3,
0x19, 0x3, 0x12, 0x3, 0xb, 0x3, 0xd, 0x3, 0x9e, 0x3, 0x19, 0x3,
0x12, 0x3, 0xb, 0x3, 0xd, 0xf, 0x92, 0x3, 0x16, 0x9, 0xf, 0x3,
0xb, 0x3, 0xd, 0xf, 0x92, 0x3, 0x16, 0x9, 0xf, 0x3, 0xb, 0x3,
0xd, 0xf, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0,
0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0,
0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0,
0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0,
0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0,
0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0,
0xff, 0x0, 0xff, 0x0, 0xec,
};

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

View File

@ -15,6 +15,9 @@
#include <components/brightness/BrightnessController.h>
#include "factoryImage.h"
#include "displayapp/icons/infinitime/infinitime-nb.c"
#include "components/rle/RleDecoder.h"
#if NRF_LOG_ENABLED
#include "logging/NrfLogger.h"
@ -31,6 +34,13 @@ static constexpr uint8_t pinSpiFlashCsn = 5;
static constexpr uint8_t pinLcdCsn = 25;
static constexpr uint8_t pinLcdDataCommand = 18;
static constexpr uint8_t displayWidth = 240;
static constexpr uint8_t displayHeight = 240;
static constexpr uint8_t bytesPerPixel = 2;
static constexpr uint16_t colorWhite = 0xFFFF;
static constexpr uint16_t colorGreen = 0xE007;
Pinetime::Drivers::SpiMaster spi{Pinetime::Drivers::SpiMaster::SpiModule::SPI0, {
Pinetime::Drivers::SpiMaster::BitOrder::Msb_Lsb,
Pinetime::Drivers::SpiMaster::Modes::Mode3,
@ -49,6 +59,10 @@ Pinetime::Drivers::St7789 lcd {lcdSpi, pinLcdDataCommand};
Pinetime::Components::Gfx gfx{lcd};
Pinetime::Controllers::BrightnessController brightnessController;
void DisplayProgressBar(uint8_t percent, uint16_t color);
void DisplayLogo();
extern "C" {
void vApplicationIdleHook(void) {
@ -71,10 +85,8 @@ void SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0_IRQHandler(void) {
}
}
uint8_t displayBuffer[displayWidth * bytesPerPixel];
void Process(void* instance) {
// Wait before erasing the memory to let the time to the SWD debugger to flash a new firmware before running this one.
vTaskDelay(5000);
APP_GPIOTE_INIT(2);
NRF_LOG_INFO("Init...");
@ -84,49 +96,52 @@ void Process(void* instance) {
brightnessController.Init();
lcd.Init();
gfx.Init();
NRF_LOG_INFO("Init Done!")
for(int i = 0; i < 100; i++) {
for(int j = 0; j < 100; j++) {
gfx.pixel_draw(70+i, 70+j, 0x00AA);
}
}
NRF_LOG_INFO("Display logo")
DisplayLogo();
NRF_LOG_INFO("Erasing...");
for (uint32_t erased = 0; erased < sizeof(factoryImage); erased += 0x1000) {
spiNorFlash.SectorErase(erased);
}
NRF_LOG_INFO("Erase done!");
NRF_LOG_INFO("Writing graphic...");
for(int i = 0; i < 100; i++) {
for(int j = 0; j < 100; j++) {
gfx.pixel_draw(70+i, 70+j, 0xaa00);
}
}
NRF_LOG_INFO("Writing factory image...");
static constexpr uint32_t memoryChunkSize = 200;
uint8_t writeBuffer[memoryChunkSize];
for(size_t offset = 0; offset < sizeof(factoryImage); offset+=memoryChunkSize) {
std::memcpy(writeBuffer, &factoryImage[offset], memoryChunkSize);
spiNorFlash.Write(offset, writeBuffer, memoryChunkSize);
DisplayProgressBar((static_cast<float>(offset) / static_cast<float>(sizeof(factoryImage))) * 100.0f, colorWhite);
}
NRF_LOG_INFO("Writing graphic done!");
for(int i = 0; i < 100; i++) {
for(int j = 0; j < 100; j++) {
gfx.pixel_draw(70+i, 70+j, 0xffff);
}
}
NRF_LOG_INFO("Done!");
NRF_LOG_INFO("Writing factory image done!");
DisplayProgressBar(100.0f, colorGreen);
while(1) {
asm("nop" );
}
}
void DisplayLogo() {
Pinetime::Tools::RleDecoder rleDecoder(infinitime_nb, sizeof(infinitime_nb));
for(int i = 0; i < displayWidth; i++) {
rleDecoder.DecodeNext(displayBuffer, displayWidth * bytesPerPixel);
ulTaskNotifyTake(pdTRUE, 500);
lcd.BeginDrawBuffer(0, i, displayWidth, 1);
lcd.NextDrawBuffer(reinterpret_cast<const uint8_t *>(displayBuffer), displayWidth * bytesPerPixel);
}
}
void DisplayProgressBar(uint8_t percent, uint16_t color) {
static constexpr uint8_t barHeight = 20;
std::fill(displayBuffer, displayBuffer+(displayWidth * bytesPerPixel), color);
for(int i = 0; i < barHeight; i++) {
ulTaskNotifyTake(pdTRUE, 500);
uint16_t barWidth = std::min(static_cast<float>(percent) * 2.4f, static_cast<float>(displayWidth));
lcd.BeginDrawBuffer(0, displayWidth - barHeight + i, barWidth, 1);
lcd.NextDrawBuffer(reinterpret_cast<const uint8_t *>(displayBuffer), barWidth * bytesPerPixel);
}
}
int main(void) {
TaskHandle_t taskHandle;

View File

@ -1,136 +0,0 @@
#include <legacy/nrf_drv_clock.h>
#include <softdevice/common/nrf_sdh.h>
#include <drivers/SpiMaster.h>
#include <drivers/Spi.h>
#include <drivers/SpiNorFlash.h>
#include <libraries/log/nrf_log.h>
#include "bootloader/boot_graphics.h"
#include <FreeRTOS.h>
#include <task.h>
#include <legacy/nrf_drv_gpiote.h>
#include <libraries/gpiote/app_gpiote.h>
#include <hal/nrf_wdt.h>
#include <cstring>
#include <components/gfx/Gfx.h>
#include <drivers/St7789.h>
#include <components/brightness/BrightnessController.h>
#if NRF_LOG_ENABLED
#include "logging/NrfLogger.h"
Pinetime::Logging::NrfLogger logger;
#else
#include "logging/DummyLogger.h"
Pinetime::Logging::DummyLogger logger;
#endif
static constexpr uint8_t pinSpiSck = 2;
static constexpr uint8_t pinSpiMosi = 3;
static constexpr uint8_t pinSpiMiso = 4;
static constexpr uint8_t pinSpiFlashCsn = 5;
static constexpr uint8_t pinLcdCsn = 25;
static constexpr uint8_t pinLcdDataCommand = 18;
Pinetime::Drivers::SpiMaster spi{Pinetime::Drivers::SpiMaster::SpiModule::SPI0, {
Pinetime::Drivers::SpiMaster::BitOrder::Msb_Lsb,
Pinetime::Drivers::SpiMaster::Modes::Mode3,
Pinetime::Drivers::SpiMaster::Frequencies::Freq8Mhz,
pinSpiSck,
pinSpiMosi,
pinSpiMiso
}
};
Pinetime::Drivers::Spi flashSpi{spi, pinSpiFlashCsn};
Pinetime::Drivers::SpiNorFlash spiNorFlash{flashSpi};
Pinetime::Drivers::Spi lcdSpi {spi, pinLcdCsn};
Pinetime::Drivers::St7789 lcd {lcdSpi, pinLcdDataCommand};
Pinetime::Components::Gfx gfx{lcd};
Pinetime::Controllers::BrightnessController brightnessController;
extern "C" {
void vApplicationIdleHook(void) {
}
void SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0_IRQHandler(void) {
if(((NRF_SPIM0->INTENSET & (1<<6)) != 0) && NRF_SPIM0->EVENTS_END == 1) {
NRF_SPIM0->EVENTS_END = 0;
spi.OnEndEvent();
}
if(((NRF_SPIM0->INTENSET & (1<<19)) != 0) && NRF_SPIM0->EVENTS_STARTED == 1) {
NRF_SPIM0->EVENTS_STARTED = 0;
spi.OnStartedEvent();
}
if(((NRF_SPIM0->INTENSET & (1<<1)) != 0) && NRF_SPIM0->EVENTS_STOPPED == 1) {
NRF_SPIM0->EVENTS_STOPPED = 0;
}
}
}
void Process(void* instance) {
// Wait before erasing the memory to let the time to the SWD debugger to flash a new firmware before running this one.
vTaskDelay(5000);
APP_GPIOTE_INIT(2);
NRF_LOG_INFO("Init...");
spi.Init();
spiNorFlash.Init();
spiNorFlash.Wakeup();
brightnessController.Init();
lcd.Init();
gfx.Init();
NRF_LOG_INFO("Init Done!")
NRF_LOG_INFO("Erasing...");
for (uint32_t erased = 0; erased < graphicSize; erased += 0x1000) {
spiNorFlash.SectorErase(erased);
}
NRF_LOG_INFO("Erase done!");
NRF_LOG_INFO("Writing graphic...");
static constexpr uint32_t memoryChunkSize = 200;
uint8_t writeBuffer[memoryChunkSize];
for(int offset = 0; offset < 115200; offset+=memoryChunkSize) {
std::memcpy(writeBuffer, &graphicBuffer[offset], memoryChunkSize);
spiNorFlash.Write(offset, writeBuffer, memoryChunkSize);
}
NRF_LOG_INFO("Writing graphic done!");
NRF_LOG_INFO("Read memory and display the graphic...");
static constexpr uint32_t screenWidth = 240;
static constexpr uint32_t screenWidthInBytes = screenWidth*2; // LCD display 16bits color (1 pixel = 2 bytes)
uint16_t displayLineBuffer[screenWidth];
for(uint32_t line = 0; line < screenWidth; line++) {
spiNorFlash.Read(line*screenWidthInBytes, reinterpret_cast<uint8_t *>(displayLineBuffer), screenWidth);
spiNorFlash.Read((line*screenWidthInBytes)+screenWidth, reinterpret_cast<uint8_t *>(displayLineBuffer) + screenWidth, screenWidth);
for(uint32_t col = 0; col < screenWidth; col++) {
gfx.pixel_draw(col, line, displayLineBuffer[col]);
}
}
NRF_LOG_INFO("Done!");
while(1) {
asm("nop" );
}
}
int main(void) {
TaskHandle_t taskHandle;
logger.Init();
nrf_drv_clock_init();
if (pdPASS != xTaskCreate(Process, "MAIN", 512, nullptr, 0, &taskHandle))
APP_ERROR_HANDLER(NRF_ERROR_NO_MEM);
vTaskStartScheduler();
for (;;) {
APP_ERROR_HANDLER(NRF_ERROR_FORBIDDEN);
}
}

379
tools/rle_encode.py Executable file
View File

@ -0,0 +1,379 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: LGPL-3.0-or-later
# Copyright (C) 2020 Daniel Thompson
import argparse
import sys
import os.path
from PIL import Image
def clut8_rgb888(i):
"""Reference CLUT for wasp-os.
Technically speaking this is not a CLUT because the we lookup the colours
algorithmically to avoid the cost of a genuine CLUT. The palette is
designed to be fairly easy to generate algorithmically.
The palette includes all 216 web-safe colours together 4 grays and
36 additional colours that target "gaps" at the brighter end of the web
safe set. There are 11 greys (plus black and white) although two are
fairly close together.
:param int i: Index (from 0..255 inclusive) into the CLUT
:return: 24-bit colour in RGB888 format
"""
if i < 216:
rgb888 = ( i % 6) * 0x33
rg = i // 6
rgb888 += (rg % 6) * 0x3300
rgb888 += (rg // 6) * 0x330000
elif i < 252:
i -= 216
rgb888 = 0x7f + (( i % 3) * 0x33)
rg = i // 3
rgb888 += 0x4c00 + ((rg % 4) * 0x3300)
rgb888 += 0x7f0000 + ((rg // 4) * 0x330000)
else:
i -= 252
rgb888 = 0x2c2c2c + (0x101010 * i)
return rgb888
def clut8_rgb565(i):
"""RBG565 CLUT for wasp-os.
This CLUT implements the same palette as :py:meth:`clut8_888` but
outputs RGB565 pixels.
.. note::
This function is unused within this file but needs to be
maintained alongside the reference clut so it is reproduced
here.
:param int i: Index (from 0..255 inclusive) into the CLUT
:return: 16-bit colour in RGB565 format
"""
if i < 216:
rgb565 = (( i % 6) * 0x33) >> 3
rg = i // 6
rgb565 += ((rg % 6) * (0x33 << 3)) & 0x07e0
rgb565 += ((rg // 6) * (0x33 << 8)) & 0xf800
elif i < 252:
i -= 216
rgb565 = (0x7f + (( i % 3) * 0x33)) >> 3
rg = i // 3
rgb565 += ((0x4c << 3) + ((rg % 4) * (0x33 << 3))) & 0x07e0
rgb565 += ((0x7f << 8) + ((rg // 4) * (0x33 << 8))) & 0xf800
else:
i -= 252
gr6 = (0x2c + (0x10 * i)) >> 2
gr5 = gr6 >> 1
rgb565 = (gr5 << 11) + (gr6 << 5) + gr5
return rgb565
class ReverseCLUT:
def __init__(self, clut):
l = []
for i in range(256):
l.append(clut(i))
self.clut = tuple(l)
self.lookup = {}
def __call__(self, rgb888):
"""Compare rgb888 to every element of the CLUT and pick the
closest match.
"""
if rgb888 in self.lookup:
return self.lookup[rgb888]
best = 200000
index = -1
clut = self.clut
r = rgb888 >> 16
g = (rgb888 >> 8) & 0xff
b = rgb888 & 0xff
for i in range(256):
candidate = clut[i]
rd = r - (candidate >> 16)
gd = g - ((candidate >> 8) & 0xff)
bd = b - (candidate & 0xff)
# This is the Euclidian distance (squared)
distance = rd * rd + gd * gd + bd * bd
if distance < best:
best = distance
index = i
self.lookup[rgb888] = index
#print(f'# #{rgb888:06x} -> #{clut8_rgb888(index):06x}')
return index
def varname(p):
return os.path.basename(os.path.splitext(p)[0])
def encode(im):
pixels = im.load()
rle = []
rl = 0
px = pixels[0, 0]
def encode_pixel(px, rl):
while rl > 255:
rle.append(255)
rle.append(0)
rl -= 255
rle.append(rl)
for y in range(im.height):
for x in range(im.width):
newpx = pixels[x, y]
if newpx == px:
rl += 1
assert(rl < (1 << 21))
continue
# Code the previous run
encode_pixel(px, rl)
# Start a new run
rl = 1
px = newpx
# Handle the final run
encode_pixel(px, rl)
return (im.width, im.height, bytes(rle))
def encode_2bit(im):
"""2-bit palette based RLE encoder.
This encoder has a reprogrammable 2-bit palette. This allows it to encode
arbitrary images with a full 8-bit depth but the 2-byte overhead each time
a new colour is introduced means it is not efficient unless the image is
carefully constructed to keep a good locality of reference for the three
non-background colours.
The encoding competes well with the 1-bit encoder for small monochrome
images but once run-lengths longer than 62 start to become frequent then
this encoding is about 30% larger than a 1-bit encoding.
"""
pixels = im.load()
assert(im.width <= 255)
assert(im.height <= 255)
full_palette = ReverseCLUT(clut8_rgb888)
rle = []
rl = 0
px = pixels[0, 0]
# black, grey25, grey50, white
palette = [0, 254, 219, 215]
next_color = 1
def encode_pixel(px, rl):
nonlocal next_color
px = full_palette((px[0] << 16) + (px[1] << 8) + px[2])
if px not in palette:
rle.append(next_color << 6)
rle.append(px)
palette[next_color] = px
next_color += 1
if next_color >= len(palette):
next_color = 1
px = palette.index(px)
if rl >= 63:
rle.append((px << 6) + 63)
rl -= 63
while rl >= 255:
rle.append(255)
rl -= 255
rle.append(rl)
else:
rle.append((px << 6) + rl)
# Issue the descriptor
rle.append(2)
rle.append(im.width)
rle.append(im.height)
for y in range(im.height):
for x in range(im.width):
newpx = pixels[x, y]
if newpx == px:
rl += 1
assert(rl < (1 << 21))
continue
# Code the previous run
encode_pixel(px, rl)
# Start a new run
rl = 1
px = newpx
# Handle the final run
encode_pixel(px, rl)
return bytes(rle)
def encode_8bit(im):
"""Experimental 8-bit RLE encoder.
For monochrome images this is about 3x less efficient than the 1-bit
encoder. This encoder is not currently used anywhere in wasp-os and
currently there is no decoder either (so don't assume this code
actually works).
"""
pixels = im.load()
rle = []
rl = 0
px = pixels[0, 0]
def encode_pixel(px, rl):
px = (px[0] & 0xe0) | ((px[1] & 0xe0) >> 3) | ((px[2] & 0xc0) >> 6)
rle.append(px)
if rl > 0:
rle.append(px)
rl -= 2
if rl > (1 << 14):
rle.append(0x80 | ((rl >> 14) & 0x7f))
if rl > (1 << 7):
rle.append(0x80 | ((rl >> 7) & 0x7f))
if rl >= 0:
rle.append( rl & 0x7f )
for y in range(im.height):
for x in range(im.width):
newpx = pixels[x, y]
if newpx == px:
rl += 1
assert(rl < (1 << 21))
continue
# Code the previous run
encode_pixel(px, rl)
# Start a new run
rl = 1
px = newpx
# Handle the final run
encode_pixel(px, rl)
return (im.width, im.height, bytes(rle))
def render_c(image, fname, indent, depth):
extra_indent = ' ' * indent
if len(image) == 3:
print(f'{extra_indent}// {depth}-bit RLE, generated from {fname}, '
f'{len(image[2])} bytes')
(x, y, pixels) = image
else:
print(f'{extra_indent}// {depth}-bit RLE, generated from {fname}, '
f'{len(image)} bytes')
pixels = image
print(f'{extra_indent}static const uint8_t {varname(fname)}[] = {{')
print(f'{extra_indent} ', end='')
i = 0
for rl in pixels:
print(f' {hex(rl)},', end='')
i += 1
if i == 12:
print(f'\n{extra_indent} ', end='')
i = 0
print('\n};')
def render_py(image, fname, indent, depth):
extra_indent = ' ' * indent
if len(image) == 3:
print(f'{extra_indent}# {depth}-bit RLE, generated from {fname}, '
f'{len(image[2])} bytes')
(x, y, pixels) = image
print(f'{extra_indent}{varname(fname)} = (')
print(f'{extra_indent} {x}, {y},')
else:
print(f'{extra_indent}# {depth}-bit RLE, generated from {fname}, '
f'{len(image)} bytes')
pixels = image[3:]
print(f'{extra_indent}{varname(fname)} = (')
print(f'{extra_indent} {image[0:1]}')
print(f'{extra_indent} {image[1:3]}')
# Split the bytestring to ensure each line is short enough to
# be absorbed on the target if needed.
for i in range(0, len(pixels), 16):
print(f'{extra_indent} {pixels[i:i+16]}')
print(f'{extra_indent})')
def decode_to_ascii(image):
(sx, sy, rle) = image
data = bytearray(2*sx)
dp = 0
black = ord('#')
white = ord(' ')
color = black
for rl in rle:
while rl:
data[dp] = color
data[dp+1] = color
dp += 2
rl -= 1
if dp >= (2*sx):
print(data.decode('utf-8'))
dp = 0
if color == black:
color = white
else:
color = black
# Check the image is the correct length
assert(dp == 0)
parser = argparse.ArgumentParser(description='RLE encoder tool.')
parser.add_argument('files', nargs='+',
help='files to be encoded')
parser.add_argument('--ascii', action='store_true',
help='Run the resulting image(s) through an ascii art decoder')
parser.add_argument('--c', action='store_true',
help='Render the output as C instead of python')
parser.add_argument('--indent', default=0, type=int,
help='Add extra indentation in the generated code')
parser.add_argument('--2bit', action='store_true', dest='twobit',
help='Generate 2-bit image')
parser.add_argument('--8bit', action='store_true', dest='eightbit',
help='Generate 8-bit image')
args = parser.parse_args()
if args.eightbit:
encoder = encode_8bit
depth = 8
elif args.twobit:
encoder = encode_2bit
depth = 2
else:
encoder = encode
depth =1
for fname in args.files:
image = encoder(Image.open(fname))
if args.c:
render_c(image, fname, args.indent, depth)
else:
render_py(image, fname, args.indent, depth)
if args.ascii:
print()
decode_to_ascii(image)