diff --git a/aseprite_c/font/arrow_down.ico b/aseprite_c/font/arrow_down.ico new file mode 100644 index 0000000..6baefc5 Binary files /dev/null and b/aseprite_c/font/arrow_down.ico differ diff --git a/aseprite_c/font/arrow_left.ico b/aseprite_c/font/arrow_left.ico new file mode 100644 index 0000000..e64cc0e Binary files /dev/null and b/aseprite_c/font/arrow_left.ico differ diff --git a/aseprite_c/font/arrow_right.ico b/aseprite_c/font/arrow_right.ico new file mode 100644 index 0000000..7286f7d Binary files /dev/null and b/aseprite_c/font/arrow_right.ico differ diff --git a/aseprite_c/font/arrow_up.ico b/aseprite_c/font/arrow_up.ico new file mode 100644 index 0000000..202c2b7 Binary files /dev/null and b/aseprite_c/font/arrow_up.ico differ diff --git a/aseprite_c/font/back.ico b/aseprite_c/font/back.ico new file mode 100644 index 0000000..aadc6c8 Binary files /dev/null and b/aseprite_c/font/back.ico differ diff --git a/aseprite_c/font/clock.ico b/aseprite_c/font/clock.ico new file mode 100644 index 0000000..b555747 Binary files /dev/null and b/aseprite_c/font/clock.ico differ diff --git a/aseprite_c/font/cross.ico b/aseprite_c/font/cross.ico new file mode 100644 index 0000000..5fb4b8c Binary files /dev/null and b/aseprite_c/font/cross.ico differ diff --git a/aseprite_c/font/degree.ico b/aseprite_c/font/degree.ico new file mode 100644 index 0000000..0146d7e Binary files /dev/null and b/aseprite_c/font/degree.ico differ diff --git a/aseprite_c/font/hourglass.ico b/aseprite_c/font/hourglass.ico new file mode 100644 index 0000000..c98a7db Binary files /dev/null and b/aseprite_c/font/hourglass.ico differ diff --git a/aseprite_c/font/ico2h b/aseprite_c/font/ico2h new file mode 100755 index 0000000..83a524e Binary files /dev/null and b/aseprite_c/font/ico2h differ diff --git a/aseprite_c/font/ico2h.rs b/aseprite_c/font/ico2h.rs new file mode 100644 index 0000000..cff87b3 --- /dev/null +++ b/aseprite_c/font/ico2h.rs @@ -0,0 +1,56 @@ +use std::fs; +use std::process::Command; +use std::string::ToString; + +fn main() { + for entry in fs::read_dir(".").unwrap() { + let entry = entry.unwrap(); + let path = entry.path(); + + if !path.display().to_string().ends_with(".ico") { + continue; + } + + let name = path.file_stem().unwrap().to_str().unwrap(); + + Command::new("/bin/convert").arg(&path).arg("./tmp.xbm").output().unwrap(); + + let content = fs::read_to_string("./tmp.xbm").unwrap(); + + let a = content.find('{').unwrap() + 1; + let b = content.find('}').unwrap(); + + let bytes = &content[a..b].trim(); + + let bytes = bytes.split(",") + .map(|s| s.trim()) + .filter(|s| !s.is_empty()) + .map(|s| u8::from_str_radix(&s[2..], 16).unwrap()) + .collect::>(); + + assert!(bytes.len() == 8); + + let mut columns : [u8; 5] = [0,0,0,0,0]; + + for (n, r) in bytes.iter().enumerate() { + for i in 0..5 { + if 0 != *r & (1< bool { + c.is_alphanumeric() || c=='_' + } + + let mut name = name.replace(|c:char|!testchar(c), "_"); + if !name.starts_with(testchar) { + name = format!("_{}", name); + } + + println!("const uint8_t {}[5] = {{ {} }};", name, columns.iter().map(|c| format!("{:#04x}", !c)).collect::>().join(", ")); + } + + let _ = fs::remove_file("./tmp.xbm"); +} diff --git a/aseprite_c/font/return.ico b/aseprite_c/font/return.ico new file mode 100644 index 0000000..6a68dac Binary files /dev/null and b/aseprite_c/font/return.ico differ diff --git a/aseprite_c/font/thermometer.ico b/aseprite_c/font/thermometer.ico new file mode 100644 index 0000000..6f386fa Binary files /dev/null and b/aseprite_c/font/thermometer.ico differ diff --git a/aseprite_c/font/tri_left.ico b/aseprite_c/font/tri_left.ico new file mode 100644 index 0000000..bd960df Binary files /dev/null and b/aseprite_c/font/tri_left.ico differ diff --git a/aseprite_c/font/tri_right.ico b/aseprite_c/font/tri_right.ico new file mode 100644 index 0000000..a600d31 Binary files /dev/null and b/aseprite_c/font/tri_right.ico differ diff --git a/aseprite_c/font/wheel.ico b/aseprite_c/font/wheel.ico new file mode 100644 index 0000000..bbcb841 Binary files /dev/null and b/aseprite_c/font/wheel.ico differ diff --git a/aseprite_c/graphics/bitmaps.c b/aseprite_c/graphics/bitmaps.c new file mode 100644 index 0000000..458a5b1 --- /dev/null +++ b/aseprite_c/graphics/bitmaps.c @@ -0,0 +1,71 @@ +#include "bitmaps.h" +#include +#include + + +/* 84x48: boot_logo */ +// ···················································································· +// ·····································································████████······· +// ························································█████████████····█···██····· +// ···················█·······························█████····█·███·····███······█···· +// ······█·█····································██████···██·█████··███████·········█··· +// ·······█······························███████····██·█████·█·······███··········█···· +// ······█·█······················███████·····███·███████··██···················██····· +// ···························██████·██·███·███·███████████·████·············███······· +// ······················████████████·██··███··█████████·█████·············██·██······· +// ··················█████·██·████···█·████···███████·███·············█████···██······· +// ·············███████████·█████████████···██·······█············█████··█·█·█·██······ +// ············██████████·██████████··███████·················█████··█·██·█···███······ +// ·········██████··█··████·██·███···████·█···············████···█··███··█······██····· +// ······███·████████████████████··██················█████··█···█·█·█···········█·█···· +// ···███████····················██··············████·█····█·····█················█···· +// ····██··························█·············█···█····██······················█···· +// ··██·····························█·······█·█·█···█····██·······················█···· +// ·█······························█·······█·█·█···█·█····························█···· +// ·█····························██·······█·█·█·····█····················█········█···· +// ··██······················████·█·█·█··█·······························█······█··█··· +// ····████···················█··█·█·█··█································█······█··█··· +// ·······█···················██·█·██··························█·········█······█··█··· +// ·······█····················█·██······█·····················█··········█·····█··█··· +// ·······█····················█·█········█··········█··········█·········█·····███···· +// ········█···················█··········█···········█·········█·····██████████······· +// ········█····················█·········█············█·········█·███················· +// ········█····················█··········█···········█·······████···················· +// ········█·····················█·········█············█·█████························ +// ········█······················█·········█·········████····························· +// ········█·······················█········█····█████···██················█·█········· +// ·········█······················█·········█·██···························█·········· +// ·········█······················█·······████····························█·█········· +// ·········█······················█····███·····················█······················ +// ·········█·······················████·······················███····················· +// ·········█·····················███···························█······················ +// ·········█········██████████████···················································· +// ··········█·██████·····························································█···· +// ···········█····························································█······█···· +// ··························································█············█·······█···· +// ··████·································█··················█······██····█··█····█···· +// ··█···█···██████···█████████····█·····███████···███████···█·····█··█····█·██····█··· +// ··█···█··██·····█·█·█··········█·█······█····█·█·█·······█·····█····█···█··█····█··· +// ··████····█·····██··█··········█·█······█····█···██████··█·····█····█···█··█····█··· +// ··█···█···██████··███████·····█···█·····█···█··███·······█·····█···█·····█·██···█··· +// ··█····█··██········█········███████····█··█·····█·······█······█·█······█·█·█·█···· +// ··█···█···█·██······█·····██··█····█··█████······█········█████··█········█···█····· +// ██████····█···███····█████···█·····██············█·································· +// ··········█·····█··································································· +static const uint8_t G_BOOT_LOGO_BYTES[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x20, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0xc0, 0xc0, 0x40, 0xc0, 0xc0, 0x40, 0xc0, 0xa0, 0xa0, 0x20, 0xa0, 0xa0, 0xe0, 0x60, 0xd0, 0x90, 0xd0, 0xd0, 0xf0, 0xf0, 0xc8, 0xe8, 0xe8, 0xb8, 0xb8, 0x64, 0xd4, 0xb4, 0x94, 0x9c, 0x14, 0x0c, 0x0c, 0x1c, 0x14, 0x34, 0x34, 0x34, 0x12, 0x1a, 0x0a, 0x0a, 0x06, 0x82, 0x82, 0x82, 0x44, 0x44, 0x28, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0xc0, 0xc0, 0x60, 0x60, 0x60, 0x50, 0x30, 0x30, 0x38, 0x3c, 0x3c, 0x2c, 0x2c, 0x3c, 0x2e, 0x2e, 0x3e, 0x3e, 0x37, 0x3d, 0x2b, 0x3f, 0x3d, 0x2f, 0x3f, 0x3f, 0x5f, 0x4d, 0xad, 0x25, 0x16, 0x1d, 0x1f, 0x1e, 0x0a, 0x1b, 0x09, 0x0d, 0x04, 0x02, 0x03, 0x03, 0xc3, 0x43, 0x43, 0x43, 0xa5, 0x63, 0x23, 0x22, 0x21, 0x91, 0xd1, 0x31, 0x11, 0x08, 0x08, 0x28, 0x58, 0x2c, 0x04, 0x34, 0x1c, 0x16, 0x0a, 0x0a, 0x16, 0x0a, 0x05, 0x01, 0x04, 0x0b, 0x0f, 0x3c, 0x10, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x09, 0x09, 0x10, 0x10, 0x10, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x38, 0xe8, 0x08, 0xf4, 0x4c, 0x32, 0x29, 0x10, 0x08, 0x00, 0x10, 0x48, 0x84, 0x02, 0x05, 0x02, 0x05, 0x02, 0x01, 0x00, 0x00, 0x02, 0x05, 0x82, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x60, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x80, 0x87, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x06, 0x08, 0x10, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x8c, 0xb0, 0xc0, 0x80, 0x40, 0x40, 0x20, 0x20, 0x20, 0x20, 0x20, 0x11, 0x16, 0x18, 0x30, 0x28, 0x08, 0x08, 0x08, 0x08, 0x04, 0x05, 0x06, 0x04, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0xa1, 0x41, 0xa1, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x0f, 0x10, 0x20, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x0c, 0x05, 0x06, 0x02, 0x02, 0x02, 0x01, 0x01, 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x02, 0x07, 0x02, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x20, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0x7f, 0x44, 0x44, 0x44, 0x2b, 0x10, 0x00, 0x02, 0xff, 0x19, 0x29, 0x29, 0x49, 0x49, 0xc6, 0x04, 0x0a, 0x09, 0x3f, 0x49, 0x49, 0x49, 0x49, 0x41, 0x21, 0x21, 0x00, 0x50, 0x38, 0x16, 0x11, 0x16, 0x18, 0x70, 0x40, 0x00, 0x21, 0x21, 0x3f, 0x21, 0x21, 0x11, 0x09, 0x06, 0x00, 0x0a, 0x09, 0x7f, 0x05, 0x05, 0x05, 0x05, 0x05, 0x00, 0x00, 0x1e, 0x21, 0x20, 0x20, 0x20, 0x20, 0x0e, 0x11, 0x20, 0x10, 0x09, 0x06, 0x00, 0x00, 0x00, 0x07, 0x18, 0x21, 0x1f, 0x08, 0x10, 0x20, 0x10, 0x0f, 0x00, 0x00, 0x00 }; + +static const struct BitmapImage bitmaps[] = { + { .name="boot_logo", .width=84, .height=48, .bytes=G_BOOT_LOGO_BYTES }, + {} +}; + +const struct BitmapImage *Bitmap_Get(const char *name) { + const struct BitmapImage *ptr = &bitmaps[0]; + while (ptr->name) { + if (0 == strcmp(ptr->name, name)) { + return ptr; + } + } + return NULL; +} + \ No newline at end of file diff --git a/aseprite_c/graphics/boot_logo.ico b/aseprite_c/graphics/boot_logo.ico new file mode 100644 index 0000000..d77e0aa Binary files /dev/null and b/aseprite_c/graphics/boot_logo.ico differ diff --git a/aseprite_c/graphics/gfx2h b/aseprite_c/graphics/gfx2h new file mode 100755 index 0000000..4c68f2e Binary files /dev/null and b/aseprite_c/graphics/gfx2h differ diff --git a/aseprite_c/graphics/gfx2h.rs b/aseprite_c/graphics/gfx2h.rs new file mode 100644 index 0000000..81ded79 --- /dev/null +++ b/aseprite_c/graphics/gfx2h.rs @@ -0,0 +1,171 @@ +use std::fs::{self,OpenOptions}; +use std::process::Command; +use std::string::ToString; +use std::io::Write; + +fn main() { + let mut c_constants = Vec::new(); + let mut c_table = Vec::new(); + + for entry in fs::read_dir(".").unwrap() { + let entry = entry.unwrap(); + let path = entry.path(); + + if !path.display().to_string().ends_with(".ico") { + continue; + } + + let name = path.file_stem().unwrap().to_str().unwrap(); + + Command::new("/bin/convert").arg(&path).arg("./tmp.xbm").output().unwrap(); + + let content = fs::read_to_string("./tmp.xbm").unwrap(); + + println!("\n------------------------------------------------------------------------\n"); + + println!("{}", content); + + let mut lines = content.lines(); + let l1 = lines.nth(0).unwrap(); + let l2 = lines.nth(0).unwrap(); + + let w : usize = l1[l1.find("width").unwrap()+6..].parse().unwrap(); + let h : usize = l2[l2.find("height").unwrap()+7..].parse().unwrap(); + + let a = content.find('{').unwrap() + 1; + let b = content.find('}').unwrap(); + let bytes = &content[a..b].trim(); + + let bytes = bytes.split(",") + .map(|s| s.trim()) + .filter(|s| !s.is_empty()) + .map(|s| ! u8::from_str_radix(&s[2..], 16).unwrap()) + .collect::>(); + + + print!("---SOURCE--\n"); + for y in 0..h { + for x in 0..(w-1)/8+1 { + for xx in 0..8 { + if (bytes[y*(((w-1)/8+1)) + x] & (1u8 << xx)) != 0 { + print!("█"); + } else { + print!("·"); + } + } + } + print!("\n"); + } + println!("---\n"); + + println!("name {},\nw {} h {},\nbytes {}", name, w, h, bytes.iter().map(|c| format!("{:#04x}", c)).collect::>().join(", ")); + + let bit_xy = |x : usize, y : usize| { + let xx = x / 8; + let nthbit = x % 8; + let n = y*((w-1)/8+1) + xx; + if n >= bytes.len() { + 0u8 + } else { + let r = ((bytes[n] & (1 << nthbit)) >> nthbit) as u8; + r + } + }; + + let result_cols = w; + let result_rows = ((h-1)/8)+1; + + let mut result = Vec::new(); + + for y in 0..result_rows { + for x in 0..result_cols { + let mut buf = 0u8; + for yy in 0..8 { + buf |= bit_xy(x, y * 8 + yy) << yy; + } + result.push(buf); + } + } + + //println!("final bytes {}", result.iter().map(|c| format!("{:#04x}", c)).collect::>().join(", ")); + + let mut render = String::new(); + print!("---\n"); + for y in 0..result_rows { + for yy in 0..8 { + if y*8+yy >= h { + break; + } + render.push_str("// "); + for x in 0..result_cols { + if (result[y*result_cols + x] & (1u8 << yy)) != 0 { + print!("█"); + render.push_str("█"); + } else { + print!("·"); + render.push_str("·"); + } + } + if yy == 7 { + print!("/ end of byte row"); + } + render.push_str("\n"); + print!("\n"); + } + } + println!("---\n"); + + fn testchar(c : char) -> bool { + c.is_alphanumeric() || c=='_' + } + + let mut name = name.replace(|c:char|!testchar(c), "_"); + if !name.starts_with(testchar) { + name = format!("_{}", name); + } + + c_constants.push(format!("\n/* {}x{}: {} */\n{}static const uint8_t G_{}_BYTES[] = {{ {} }};", + w,h, + name, + render, + name.to_uppercase(), + result.iter().map(|c| format!("{:#04x}", c)).collect::>().join(", ") + )); + + c_table.push(format!("{{ .name=\"{}\", .width={}, .height={}, .bytes=G_{}_BYTES }}", + name, + w, h, + name.to_uppercase() + )); + } + + let c_source = format!(r##"#include "bitmaps.h" +#include +#include + +{} + +static const struct BitmapImage bitmaps[] = {{ + {}, + {{}} +}}; + +const struct BitmapImage *Bitmap_Get(const char *name) {{ + const struct BitmapImage *ptr = &bitmaps[0]; + while (ptr->name) {{ + if (0 == strcmp(ptr->name, name)) {{ + return ptr; + }} + }} + return NULL; +}} + "##, + c_constants.join("\n"), + c_table.join(",\n ") + ); + + let mut f = OpenOptions::new().write(true).create(true).truncate(true).open("./bitmaps.c").unwrap(); + f.write(c_source.as_bytes()).unwrap(); + + let _ = fs::remove_file("./tmp.xbm"); +} diff --git a/aseprite_c/graphics/unittests/12x8.ico b/aseprite_c/graphics/unittests/12x8.ico new file mode 100644 index 0000000..78936df Binary files /dev/null and b/aseprite_c/graphics/unittests/12x8.ico differ diff --git a/aseprite_c/graphics/unittests/3x3.ico b/aseprite_c/graphics/unittests/3x3.ico new file mode 100644 index 0000000..82a4436 Binary files /dev/null and b/aseprite_c/graphics/unittests/3x3.ico differ diff --git a/aseprite_c/graphics/unittests/8x12.ico b/aseprite_c/graphics/unittests/8x12.ico new file mode 100644 index 0000000..8b78247 Binary files /dev/null and b/aseprite_c/graphics/unittests/8x12.ico differ diff --git a/aseprite_c/graphics/unittests/8x8.ico b/aseprite_c/graphics/unittests/8x8.ico new file mode 100644 index 0000000..fbe45b8 Binary files /dev/null and b/aseprite_c/graphics/unittests/8x8.ico differ diff --git a/main/CMakeLists.txt b/main/CMakeLists.txt index 50e93a7..324bd0e 100644 --- a/main/CMakeLists.txt +++ b/main/CMakeLists.txt @@ -6,10 +6,13 @@ set(COMPONENT_SRCS "liquid/liquid.c" "scenes/scene_root.c" "scenes/scene_car.c" + "scenes/scene_demo.c" + "scenes/scene_bootanim.c" "graphics/nokia.c" "graphics/utf8.c" "graphics/font.c" "graphics/drawing.c" + "graphics/bitmaps.c" ) set(COMPONENT_ADD_INCLUDEDIRS "." "liquid" "graphics") diff --git a/main/graphics/bitmaps.c b/main/graphics/bitmaps.c new file mode 100644 index 0000000..458a5b1 --- /dev/null +++ b/main/graphics/bitmaps.c @@ -0,0 +1,71 @@ +#include "bitmaps.h" +#include +#include + + +/* 84x48: boot_logo */ +// ···················································································· +// ·····································································████████······· +// ························································█████████████····█···██····· +// ···················█·······························█████····█·███·····███······█···· +// ······█·█····································██████···██·█████··███████·········█··· +// ·······█······························███████····██·█████·█·······███··········█···· +// ······█·█······················███████·····███·███████··██···················██····· +// ···························██████·██·███·███·███████████·████·············███······· +// ······················████████████·██··███··█████████·█████·············██·██······· +// ··················█████·██·████···█·████···███████·███·············█████···██······· +// ·············███████████·█████████████···██·······█············█████··█·█·█·██······ +// ············██████████·██████████··███████·················█████··█·██·█···███······ +// ·········██████··█··████·██·███···████·█···············████···█··███··█······██····· +// ······███·████████████████████··██················█████··█···█·█·█···········█·█···· +// ···███████····················██··············████·█····█·····█················█···· +// ····██··························█·············█···█····██······················█···· +// ··██·····························█·······█·█·█···█····██·······················█···· +// ·█······························█·······█·█·█···█·█····························█···· +// ·█····························██·······█·█·█·····█····················█········█···· +// ··██······················████·█·█·█··█·······························█······█··█··· +// ····████···················█··█·█·█··█································█······█··█··· +// ·······█···················██·█·██··························█·········█······█··█··· +// ·······█····················█·██······█·····················█··········█·····█··█··· +// ·······█····················█·█········█··········█··········█·········█·····███···· +// ········█···················█··········█···········█·········█·····██████████······· +// ········█····················█·········█············█·········█·███················· +// ········█····················█··········█···········█·······████···················· +// ········█·····················█·········█············█·█████························ +// ········█······················█·········█·········████····························· +// ········█·······················█········█····█████···██················█·█········· +// ·········█······················█·········█·██···························█·········· +// ·········█······················█·······████····························█·█········· +// ·········█······················█····███·····················█······················ +// ·········█·······················████·······················███····················· +// ·········█·····················███···························█······················ +// ·········█········██████████████···················································· +// ··········█·██████·····························································█···· +// ···········█····························································█······█···· +// ··························································█············█·······█···· +// ··████·································█··················█······██····█··█····█···· +// ··█···█···██████···█████████····█·····███████···███████···█·····█··█····█·██····█··· +// ··█···█··██·····█·█·█··········█·█······█····█·█·█·······█·····█····█···█··█····█··· +// ··████····█·····██··█··········█·█······█····█···██████··█·····█····█···█··█····█··· +// ··█···█···██████··███████·····█···█·····█···█··███·······█·····█···█·····█·██···█··· +// ··█····█··██········█········███████····█··█·····█·······█······█·█······█·█·█·█···· +// ··█···█···█·██······█·····██··█····█··█████······█········█████··█········█···█····· +// ██████····█···███····█████···█·····██············█·································· +// ··········█·····█··································································· +static const uint8_t G_BOOT_LOGO_BYTES[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x20, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0xc0, 0xc0, 0x40, 0xc0, 0xc0, 0x40, 0xc0, 0xa0, 0xa0, 0x20, 0xa0, 0xa0, 0xe0, 0x60, 0xd0, 0x90, 0xd0, 0xd0, 0xf0, 0xf0, 0xc8, 0xe8, 0xe8, 0xb8, 0xb8, 0x64, 0xd4, 0xb4, 0x94, 0x9c, 0x14, 0x0c, 0x0c, 0x1c, 0x14, 0x34, 0x34, 0x34, 0x12, 0x1a, 0x0a, 0x0a, 0x06, 0x82, 0x82, 0x82, 0x44, 0x44, 0x28, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0xc0, 0xc0, 0x60, 0x60, 0x60, 0x50, 0x30, 0x30, 0x38, 0x3c, 0x3c, 0x2c, 0x2c, 0x3c, 0x2e, 0x2e, 0x3e, 0x3e, 0x37, 0x3d, 0x2b, 0x3f, 0x3d, 0x2f, 0x3f, 0x3f, 0x5f, 0x4d, 0xad, 0x25, 0x16, 0x1d, 0x1f, 0x1e, 0x0a, 0x1b, 0x09, 0x0d, 0x04, 0x02, 0x03, 0x03, 0xc3, 0x43, 0x43, 0x43, 0xa5, 0x63, 0x23, 0x22, 0x21, 0x91, 0xd1, 0x31, 0x11, 0x08, 0x08, 0x28, 0x58, 0x2c, 0x04, 0x34, 0x1c, 0x16, 0x0a, 0x0a, 0x16, 0x0a, 0x05, 0x01, 0x04, 0x0b, 0x0f, 0x3c, 0x10, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x09, 0x09, 0x10, 0x10, 0x10, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x38, 0xe8, 0x08, 0xf4, 0x4c, 0x32, 0x29, 0x10, 0x08, 0x00, 0x10, 0x48, 0x84, 0x02, 0x05, 0x02, 0x05, 0x02, 0x01, 0x00, 0x00, 0x02, 0x05, 0x82, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x60, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x80, 0x87, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x06, 0x08, 0x10, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x8c, 0xb0, 0xc0, 0x80, 0x40, 0x40, 0x20, 0x20, 0x20, 0x20, 0x20, 0x11, 0x16, 0x18, 0x30, 0x28, 0x08, 0x08, 0x08, 0x08, 0x04, 0x05, 0x06, 0x04, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0xa1, 0x41, 0xa1, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x0f, 0x10, 0x20, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x0c, 0x05, 0x06, 0x02, 0x02, 0x02, 0x01, 0x01, 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x02, 0x07, 0x02, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x20, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0x7f, 0x44, 0x44, 0x44, 0x2b, 0x10, 0x00, 0x02, 0xff, 0x19, 0x29, 0x29, 0x49, 0x49, 0xc6, 0x04, 0x0a, 0x09, 0x3f, 0x49, 0x49, 0x49, 0x49, 0x41, 0x21, 0x21, 0x00, 0x50, 0x38, 0x16, 0x11, 0x16, 0x18, 0x70, 0x40, 0x00, 0x21, 0x21, 0x3f, 0x21, 0x21, 0x11, 0x09, 0x06, 0x00, 0x0a, 0x09, 0x7f, 0x05, 0x05, 0x05, 0x05, 0x05, 0x00, 0x00, 0x1e, 0x21, 0x20, 0x20, 0x20, 0x20, 0x0e, 0x11, 0x20, 0x10, 0x09, 0x06, 0x00, 0x00, 0x00, 0x07, 0x18, 0x21, 0x1f, 0x08, 0x10, 0x20, 0x10, 0x0f, 0x00, 0x00, 0x00 }; + +static const struct BitmapImage bitmaps[] = { + { .name="boot_logo", .width=84, .height=48, .bytes=G_BOOT_LOGO_BYTES }, + {} +}; + +const struct BitmapImage *Bitmap_Get(const char *name) { + const struct BitmapImage *ptr = &bitmaps[0]; + while (ptr->name) { + if (0 == strcmp(ptr->name, name)) { + return ptr; + } + } + return NULL; +} + \ No newline at end of file diff --git a/main/graphics/bitmaps.h b/main/graphics/bitmaps.h new file mode 100644 index 0000000..b724044 --- /dev/null +++ b/main/graphics/bitmaps.h @@ -0,0 +1,21 @@ +/** + * TODO file description + * + * Created on 2020/01/05. + */ + +#ifndef BITMAPS_H +#define BITMAPS_H + +#include + +struct BitmapImage { + const char *name; + uint8_t width; + uint8_t height; + const uint8_t* bytes; +}; + +const struct BitmapImage *Bitmap_Get(const char *name); + +#endif //BITMAPS_H diff --git a/main/graphics/drawing.c b/main/graphics/drawing.c index b1d92bd..5e70825 100644 --- a/main/graphics/drawing.c +++ b/main/graphics/drawing.c @@ -282,12 +282,10 @@ void LCD_setStrEx(const char *dString, int x, int y, enum Color bw, uint8_t styl // This function will draw an array over the screen. (For now) the // array must be the same size as the screen, covering the entirety // of the display. -// Also, the array must reside in FLASH and declared with PROGMEM. -void LCD_setBitmap(const char *bitArray) +void LCD_setBitmap(const uint8_t *bitArray) { for (int i = 0; i < (LCD_WIDTH * LCD_HEIGHT / 8); i++) { - char c = bitArray[i]; - LCD_displayMap[i] = c; + LCD_displayMap[i] = bitArray[i]; } } diff --git a/main/graphics/drawing.h b/main/graphics/drawing.h index 6a11ea6..155486a 100644 --- a/main/graphics/drawing.h +++ b/main/graphics/drawing.h @@ -4,8 +4,8 @@ * Created on 2020/01/05. */ -#ifndef REFLOWER_DRAWING_H -#define REFLOWER_DRAWING_H +#ifndef LCD_DRAWING_H +#define LCD_DRAWING_H #include #include @@ -34,6 +34,8 @@ void LCD_setRect(int x0, int y0, int x1, int y1, bool fill, enum Color bw); // thickness ranging from 1 to the radius of the circle. void LCD_setCircle (int x0, int y0, int radius, enum Color bw, int lineThickness); +void LCD_setBitmap(const uint8_t *bitArray); + /* FONT FUNCTIONS size = 1 ... normal @@ -72,4 +74,4 @@ void LCD_clearDisplay(enum Color bw); /* Invert colors (hard change in data; does NOT send to display immediately) */ void LCD_invertDisplayData(); -#endif //REFLOWER_DRAWING_H +#endif //LCD_DRAWING_H diff --git a/main/graphics/nokia.h b/main/graphics/nokia.h index 41462d1..73b5435 100644 --- a/main/graphics/nokia.h +++ b/main/graphics/nokia.h @@ -2,8 +2,8 @@ * Driver for Nokia 5110 SPI LCD display */ -#ifndef GFX_NOKIA -#define GFX_NOKIA +#ifndef GFX_NOKIA_H +#define GFX_NOKIA_H /* Pin definitions: Most of these pins can be moved to any digital or analog pin. @@ -36,4 +36,4 @@ void LCD_invertDisplay(bool invert); //This sends the magical commands to the PCD8544 void LCD_setup(void); -#endif // GFX_NOKIA +#endif // GFX_NOKIA_H diff --git a/main/liquid/gui.c b/main/liquid/gui.c index 7f76040..ffee3ee 100644 --- a/main/liquid/gui.c +++ b/main/liquid/gui.c @@ -53,11 +53,10 @@ static void __attribute__((noreturn)) gui_thread(void *arg) { uint32_t last_wheel_time = 0; while (1) { + bool want_repaint = false; uint32_t value = 0; xTaskNotifyWait(0, ULONG_MAX, &value, pdMS_TO_TICKS(10)); - bool want_repaint = false; - if (value & 0b10000) { // TICK want_repaint |= Liquid_handleTick(liquid); @@ -72,6 +71,7 @@ static void __attribute__((noreturn)) gui_thread(void *arg) { if (value & 0b11) { uint32_t time = xTaskGetTickCount(); uint32_t increment = 1; + // wheel delta changes with speed if (last_wheel_time != 0) { uint32_t ela = time - last_wheel_time; if (ela < pdMS_TO_TICKS(20)) { diff --git a/main/liquid/liquid.c b/main/liquid/liquid.c index df78be1..ee5e65d 100644 --- a/main/liquid/liquid.c +++ b/main/liquid/liquid.c @@ -9,6 +9,8 @@ static const char *TAG = "Liquid"; extern struct Scene *NewScene_Root(void); +static struct SceneEvent Liquid_initTopScene(struct Liquid *container); +static bool processReturnValue(struct Liquid *container, struct SceneEvent result); struct RunningScene { struct Scene *scene; @@ -27,7 +29,6 @@ static struct SceneEvent Default_onChildReturn(struct Scene *scene, uint32_t tag static void addChild(struct Liquid *container, struct Scene *child) { struct RunningScene *elm = calloc(1, sizeof(struct RunningScene)); if (!child->onChildReturn) child->onChildReturn = Default_onChildReturn; - assert(child->paint != NULL); elm->scene = child; SLIST_INSERT_HEAD(&container->stack, elm, next); } @@ -36,7 +37,12 @@ struct Liquid *Liquid_start(void) { struct Liquid *container = calloc(1, sizeof(struct Liquid)); addChild(container, NewScene_Root()); - Liquid_paint(container); + + struct SceneEvent result = Liquid_initTopScene(container); + + if (processReturnValue(container, result)) { + Liquid_paint(container); + } return container; } @@ -69,7 +75,7 @@ static struct SceneEvent handleSceneEvent(struct Liquid *container, struct Scene newScene = event.open.scene; newScene->tag = event.open.tag; addChild(container, newScene); - return SceneEvent_Repaint(); + return Liquid_initTopScene(container); case SceneEventKind_RequestRepaint: case SceneEventKind_None: @@ -79,6 +85,9 @@ static struct SceneEvent handleSceneEvent(struct Liquid *container, struct Scene } } +/** + * returns true if repaint is requested + */ static bool processReturnValue(struct Liquid *container, struct SceneEvent result) { bool repaint = false; while (result.kind != SceneEventKind_None) { @@ -122,10 +131,23 @@ bool Liquid_handleTick(struct Liquid *container) { } } +static struct SceneEvent Liquid_initTopScene(struct Liquid *container) { + struct RunningScene *topmost = SLIST_FIRST(&container->stack); + assert(topmost != NULL); + assert(topmost->scene != NULL); + if (topmost->scene->init) { + return topmost->scene->init(topmost->scene); + } else { + return SceneEvent_Repaint(); + } +} + void Liquid_paint(struct Liquid *container) { struct RunningScene *topmost = SLIST_FIRST(&container->stack); assert(topmost != NULL); - topmost->scene->paint(topmost->scene); + if (topmost->scene->paint) { + topmost->scene->paint(topmost->scene); + } LCD_updateDisplay(); } diff --git a/main/liquid/scene_type.h b/main/liquid/scene_type.h index 513acdc..4d9ab82 100644 --- a/main/liquid/scene_type.h +++ b/main/liquid/scene_type.h @@ -40,6 +40,14 @@ typedef struct SceneEvent (*Scene_onChildReturn_t)(struct Scene *scene, uint32_t */ typedef struct SceneEvent (*Scene_onTick_t)(struct Scene *scene); +/** + * Scene::init fp type + * + * @param scene - self + * @return follow-up scene event, can be SceneEvent_None() if not used. + */ +typedef struct SceneEvent (*Scene_init_t)(struct Scene *scene); + /** * Scene::paint fp type * @@ -65,6 +73,12 @@ struct Scene { */ uint32_t tag; + /** + * Init function, called once after the scene has been opened. + * Nullable field. + */ + Scene_init_t init; + /** * Handle input event. * Can return a follow-up scene event, e.g. repaint request. @@ -90,8 +104,7 @@ struct Scene { /** * Draw the scene to the LCD buffer. * DO NOT write to the display yet, it will be done by the GUI engine. - * - * MANDATORY FIELD + * Nullable field. */ Scene_paint_t paint; diff --git a/main/scenes/scene_bootanim.c b/main/scenes/scene_bootanim.c new file mode 100644 index 0000000..e6921d4 --- /dev/null +++ b/main/scenes/scene_bootanim.c @@ -0,0 +1,36 @@ +#include +#include +#include + +#include "scenes.h" +#include "liquid.h" +#include "analog.h" +#include "graphics/nokia.h" +#include "graphics/drawing.h" + +struct BootScene { + struct Scene base; + uint32_t cnt; +}; + +static struct SceneEvent Boot_onTick(struct BootScene *self) { + self->cnt += 10; // ms + if (self->cnt == 2000) { + return SceneEvent_Close(0, NULL); + } + + return SceneEvent_None(); +} + +static void Boot_paint(struct BootScene *self) +{ + LCD_clearDisplay(0); + LCD_setBitmap(Bitmap_Get("boot_logo")->bytes); +} + +struct Scene *NewScene_Boot(void) { + struct BootScene *scene = calloc(1, sizeof(struct BootScene)); + scene->base.paint = (Scene_paint_t) Boot_paint; + scene->base.onTick = (Scene_onTick_t) Boot_onTick; + return (struct Scene *) scene; +} diff --git a/main/scenes/scene_demo.c b/main/scenes/scene_demo.c new file mode 100644 index 0000000..027a325 --- /dev/null +++ b/main/scenes/scene_demo.c @@ -0,0 +1,92 @@ +#include +#include +#include + +#include "scenes.h" +#include "liquid.h" +#include "analog.h" +#include "graphics/nokia.h" +#include "graphics/drawing.h" + +/** + * The struct is allocated bigger than 'Scene' to accommodate private fields. + * Since the base struct is located at the beginning, it can be cast and passed around as Scene. + */ +struct DemoScene { + struct Scene base; + int32_t pos; + uint32_t timer_phase; + uint32_t timer_prescale; +}; + +static struct SceneEvent Demo_onInput(struct DemoScene *self, struct InputEvent event) { + switch (event.kind) { + case InputEventKind_Wheel: + self->pos += event.wheel.delta; + break; + + case InputEventKind_Button: + if (event.button.state) { + return SceneEvent_OpenChild(NewScene_Car(), 0); + } + break; + } + + return SceneEvent_Repaint(); +} + +static struct SceneEvent Demo_onTick(struct DemoScene *self) { + // top text anim + self->timer_prescale += 1; + + if (self->timer_prescale == 100) { + self->timer_prescale = 0; + self->timer_phase += 1; + self->timer_phase = self->timer_phase & 0b11; // 0..3 + + return SceneEvent_Repaint(); + } + + return SceneEvent_None(); +} + +static void Demo_paint(struct DemoScene *self) +{ + LCD_clearDisplay(0); + + const char *header = "???"; + switch (self->timer_phase) { + case 0: + header = "Drink water"; + break; + case 1: + header = " Drink water"; + break; + case 2: + header = " Drink water"; + break; + case 3: + header = " Drink water"; + break; + } + + LCD_setStrEx(header, 0, 3, 1, 3); + + LCD_setRect(0, 12, 83, 31, 1, 1); + char buf[10]; +// sprintf(buf, "%3d", priv->pos); +// LCD_setStr(buf, 2, 15, 0); + sprintf(buf, "🌡%.0f°C", analog_read()); + LCD_setStrEx(buf, 2, 14, 0, 2); + + LCD_setStr("×↑↓←→⏰⌛☸⏎🌡°🔙▶◀", 2, 33, 1); +} + +struct Scene *NewScene_Demo(void) { + struct DemoScene *scene = calloc(1, sizeof(struct DemoScene)); + + scene->base.onInput = (Scene_onInput_t) Demo_onInput; + scene->base.paint = (Scene_paint_t) Demo_paint; + scene->base.onTick = (Scene_onTick_t) Demo_onTick; + return (struct Scene *) scene; +} diff --git a/main/scenes/scene_root.c b/main/scenes/scene_root.c index 68e0525..7f3e5e4 100644 --- a/main/scenes/scene_root.c +++ b/main/scenes/scene_root.c @@ -1,5 +1,6 @@ #include #include +#include #include "scenes.h" #include "liquid.h" @@ -13,78 +14,31 @@ */ struct RootScene { struct Scene base; - int32_t pos; - uint32_t timer_phase; - uint32_t timer_prescale; }; -static struct SceneEvent Root_onInput(struct RootScene *self, struct InputEvent event) { - switch (event.kind) { - case InputEventKind_Wheel: - self->pos += event.wheel.delta; - break; - - case InputEventKind_Button: - if (event.button.state) { - return SceneEvent_OpenChild(NewScene_Car(), 0); - } - break; - } - - return SceneEvent_Repaint(); -} - -static struct SceneEvent Root_onTick(struct RootScene *self) { - self->timer_prescale += 1; - - if (self->timer_prescale == 100) { - self->timer_prescale = 0; - self->timer_phase += 1; - self->timer_phase = self->timer_phase & 0b11; // 0..3 - - return SceneEvent_Repaint(); - } - - return SceneEvent_None(); +static struct SceneEvent Root_init(struct RootScene *self) +{ + return SceneEvent_OpenChild(NewScene_Boot(), 1); } -static void Root_paint(struct RootScene *self) +struct SceneEvent Root_onChildReturn( + struct RootScene *self, + uint32_t tag, + int32_t status, + void *data) { - LCD_clearDisplay(0); - const char *header = "???"; - switch (self->timer_phase) { - case 0: - header = "Drink water"; - break; - case 1: - header = " Drink water"; - break; - case 2: - header = " Drink water"; - break; - case 3: - header = " Drink water"; - break; + if (tag == 1) { + return SceneEvent_OpenChild(NewScene_Demo(), 0); } - LCD_setStrEx(header, 0, 3, 1, 3); - - LCD_setRect(0, 12, 83, 31, 1, 1); - char buf[10]; -// sprintf(buf, "%3d", priv->pos); -// LCD_setStr(buf, 2, 15, 0); - sprintf(buf, "🌡%.0f°C", analog_read()); - LCD_setStrEx(buf, 2, 14, 0, 2); - - LCD_setStr("×↑↓←→⏰⌛☸⏎🌡°🔙▶◀", 2, 33, 1); - LCD_updateDisplay(); + // this should be unreachable + return SceneEvent_None(); } struct Scene *NewScene_Root(void) { struct RootScene *scene = calloc(1, sizeof(struct RootScene)); - scene->base.onInput = (Scene_onInput_t) Root_onInput; - scene->base.paint = (Scene_paint_t) Root_paint; - scene->base.onTick = (Scene_onTick_t) Root_onTick; + scene->base.init = (Scene_init_t) Root_init; + scene->base.onChildReturn = (Scene_onChildReturn_t) Root_onChildReturn; return (struct Scene *) scene; } diff --git a/main/scenes/scenes.h b/main/scenes/scenes.h index 850251e..f9fd69b 100644 --- a/main/scenes/scenes.h +++ b/main/scenes/scenes.h @@ -8,6 +8,8 @@ #define REFLOWER_SCENES_H struct Scene *NewScene_Root(void); +struct Scene *NewScene_Boot(void); +struct Scene *NewScene_Demo(void); struct Scene *NewScene_Car(void); #endif //REFLOWER_SCENES_H