fixed some problems and added the demos for fxhelloworld, fxbasicexample and fxchompies

This commit is contained in:
ZennDev1337 2023-10-06 15:21:04 +02:00
parent 9ad03927de
commit 4a3100c0bd
18 changed files with 258 additions and 85 deletions

3
.idea/dictionaries/zenn.xml generated Normal file
View file

@ -0,0 +1,3 @@
<component name="ProjectDictionaryState">
<dictionary name="zenn" />
</component>

View file

@ -3,7 +3,7 @@
<option name="myName" value="Project Default" />
<inspection_tool class="DuplicatedCode" enabled="true" level="WEAK WARNING" enabled_by_default="true">
<Languages>
<language minSize="101" name="Rust" />
<language minSize="268" name="Rust" />
</Languages>
</inspection_tool>
</profile>

View file

@ -1,20 +1,51 @@
#![no_std]
#![allow(non_upper_case_globals)]
//Include the Arduboy Library
//Initialize the arduboy object
#[allow(unused_imports)]
use arduboy_rust::prelude::*;
#[allow(dead_code)]
const arduboy: Arduboy2 = Arduboy2::new();
//The setup() function runs once when you turn your Arduboy on
// Progmem data
// dynamic ram variables
const FX_DATA_PAGE: u16 = 0xffff;
#[allow(dead_code)]
const FX_DATA_BYTES: u32 = 234;
const FXlogo: u32 = 0x000000;
const FXlogoWith: i16 = 115;
const FXlogoHeight: i16 = 16;
static mut x: i16 = (WIDTH - FXlogoWith) / 2;
static mut y: i16 = 25;
static mut xDir: i8 = 1;
static mut yDir: i8 = 1;
// The setup() function runs once when you turn your Arduboy on
#[no_mangle]
pub unsafe extern "C" fn setup() {
// put your setup code here, to run once:
arduboy.begin();
arduboy.clear();
arduboy.print(f!(b"Holmes is cool!\0"));
arduboy.display();
arduboy.set_frame_rate(30);
fx::begin_data(FX_DATA_PAGE);
}
// The loop() function repeats forever after setup() is done
#[no_mangle]
#[export_name = "loop"]
pub unsafe extern "C" fn loop_() {
// put your main code here, to run repeatedly:
if !arduboy.next_frame() {
return;
}
fx::draw_bitmap(x, y, FXlogo, 0, 0);
x += xDir as i16;
y += yDir as i16;
if x == 0 || x == WIDTH - FXlogoWith {
xDir = -xDir;
}
if y == 0 || y == HEIGHT - FXlogoHeight {
yDir = -yDir;
}
fx::display_clear()
}

Binary file not shown.

View file

@ -1,6 +1,6 @@
#pragma once
/**** FX data header generated by fxdata-build.py tool version 1.07 ****/
/**** FX data header generated by fxdata-build.py tool version 1.15 ****/
using uint24_t = __uint24;

View file

@ -1,20 +1,105 @@
#![no_std]
#![allow(non_upper_case_globals)]
//Include the Arduboy Library
//Initialize the arduboy object
use arduboy_rust::prelude::*;
use arduboyfx::fx_consts::*;
const arduboy: Arduboy2 = Arduboy2::new();
// FX Data
const FX_DATA_PAGE: u16 = 0xff65;
const FX_DATA_BYTES: u32 = 39470;
const mapGfx: u32 = 0x000000;
const mapGfxWidth: u16 = 816;
const mapGfxHeight: u16 = 368;
const whaleGfx: u32 = 0x0092A4;
const whaleGfxWidth: u16 = 107;
const whaleGfxHeight: u16 = 69;
static mut showposition: bool = true;
static mut select: usize = 0;
static mut color: u8 = 0;
static mut x: [i16; 2] = [0, 0];
static mut y: [i16; 2] = [0, 0];
static mut mode: u8 = 0;
//The setup() function runs once when you turn your Arduboy on
#[no_mangle]
pub unsafe extern "C" fn setup() {
// put your setup code here, to run once:
arduboy.begin();
arduboy.clear();
arduboy.print(f!(b"Holmes is cool!\0"));
arduboy.display();
arduboy.set_frame_rate(120);
fx::begin_data(FX_DATA_PAGE);
}
#[no_mangle]
#[export_name = "loop"]
pub unsafe extern "C" fn loop_() {
// put your main code here, to run repeatedly:
if !arduboy.next_frame() {
return;
}
arduboy.poll_buttons();
if arduboy.pressed(A) && arduboy.pressed(B) {
if arduboy.every_x_frames(120) {
mode += 1;
if mode == 5 {
mode = 0
}
}
}
if arduboy.just_pressed(B) {
showposition = !showposition;
}
if arduboy.pressed(B) {
select = 0;
} else {
select = 1
}
if arduboy.just_pressed(A) {
color ^= dbmReverse;
}
if arduboy.pressed(A) {
if arduboy.just_pressed(UP) {
y[select] -= 1;
}
if arduboy.just_pressed(DOWN) {
y[select] += 1;
}
if arduboy.just_pressed(LEFT) {
x[select] -= 1;
}
if arduboy.just_pressed(RIGHT) {
x[select] += 1;
}
} else {
if arduboy.pressed(UP) {
y[select] -= 1;
}
if arduboy.pressed(DOWN) {
y[select] += 1;
}
if arduboy.pressed(LEFT) {
x[select] -= 1;
}
if arduboy.pressed(RIGHT) {
x[select] += 1;
}
}
fx::draw_bitmap(x[0], y[0], mapGfx, 0, dbmNormal);
match mode {
0 => fx::draw_bitmap(x[1], y[1], whaleGfx, 0, dbmMasked | color),
1 => fx::draw_bitmap(x[1], y[1], whaleGfx, 0, dbfMasked | dbmBlack),
2 => fx::draw_bitmap(x[1], y[1], whaleGfx, 0, dbfMasked | dbmWhite),
3 => fx::draw_bitmap(x[1], y[1], whaleGfx, 0, dbfMasked | dbmInvert),
4 => fx::draw_bitmap(x[1], y[1], whaleGfx, 0, dbfMasked | dbmReverse),
_ => (),
}
if showposition {
arduboy.set_cursor(0, 0);
arduboy.print(x[select]);
arduboy.set_cursor(0, 8);
arduboy.print(y[select]);
}
fx::display_clear();
}

View file

@ -1,20 +1,89 @@
#![no_std]
#![allow(non_upper_case_globals)]
//Include the Arduboy Library
//Initialize the arduboy object
use arduboy_rust::prelude::*;
use arduboyfx::fx_consts::*;
const arduboy: Arduboy2 = Arduboy2::new();
//FX Data
const FX_DATA_PAGE: u16 = 0xffc9;
const FX_DATA_BYTES: u32 = 13937;
const arduboyFont: u32 = 0x000000;
const arduboyFontWidth: u16 = 6;
const arduboyFontHeight: u16 = 8;
const arduboyFontFrames: u16 = 256;
const maskedFont: u32 = 0x000604;
const maskedFontWidth: u16 = 16;
const maskedFontHeight: u16 = 24;
const maskedFontFrames: u8 = 128;
const helloWorld: u32 = 0x003608;
static mut frames: u16 = 0;
static mut speed: u8 = 1;
static mut scroll_x: i16 = 128;
static mut font_mode: u8 = dcmNormal;
static mut leading_digits: i8 = 5;
static str: &str = "FX Demo\0";
//The setup() function runs once when you turn your Arduboy on
#[no_mangle]
pub unsafe extern "C" fn setup() {
// put your setup code here, to run once:
arduboy.begin();
arduboy.clear();
arduboy.print(f!(b"Holmes is cool!\0"));
arduboy.display();
fx::begin_data(FX_DATA_PAGE);
fx::set_font(arduboyFont, dcmNormal);
fx::set_cursor_range(0, 32767);
}
#[no_mangle]
#[export_name = "loop"]
pub unsafe extern "C" fn loop_() {
// put your main code here, to run repeatedly:
if !arduboy.next_frame() {
return;
}
arduboy.poll_buttons();
fx::set_cursor(0, 0);
fx::set_font_mode(dcmNormal);
fx::draw_string(str);
fx::set_cursor(WIDTH - 5 * arduboyFontWidth as i16, 0);
fx::draw_number(frames, leading_digits);
fx::set_cursor(scroll_x, 24);
fx::set_font(maskedFont, dcmMasked | font_mode);
fx::draw_string(helloWorld);
fx::set_cursor(13, HEIGHT - arduboyFontHeight as i16);
fx::set_font(arduboyFont, font_mode);
fx::draw_string(" Press any button \0");
fx::display_clear();
scroll_x -= speed as i16;
if scroll_x < -1792 {
scroll_x = 128
}
frames += 1;
if arduboy.just_pressed(ANY_BUTTON) {
frames = 0
}
if arduboy.just_pressed(UP) {
speed = 2
}
if arduboy.just_pressed(DOWN) {
speed = 1
}
if arduboy.just_pressed(LEFT) {
leading_digits = if leading_digits == -5 { 0 } else { -5 }
}
if arduboy.just_pressed(RIGHT) {
leading_digits = if leading_digits == 5 { 0 } else { 5 }
}
if arduboy.just_pressed(A) {
font_mode = dcmNormal
}
if arduboy.just_pressed(B) {
font_mode = dcmReverse
}
}

View file

@ -7,7 +7,6 @@ use arduboy_rust::prelude::*;
use arduboy_tones::tones_pitch::*;
mod gameloop;
#[allow(dead_code)]
pub const arduboy: Arduboy2 = Arduboy2::new();
pub const sound: ArduboyTones = ArduboyTones::new();
@ -155,7 +154,6 @@ pub unsafe extern "C" fn loop_() {
gameloop::gameloop();
}
GameMode::Losescreen => {
//todo
arduboy.set_text_size(2);
arduboy.set_cursor(13, p.gameover_height);
arduboy.print(get_string_addr!(text_gameover));

View file

@ -11,24 +11,12 @@ const arduboy: Arduboy2 = Arduboy2::new();
// Progmem data
// dynamic ram variables
const FX_DATA_PAGE: u16 = 0xffff;
#[allow(dead_code)]
const FX_DATA_BYTES: u32 = 234;
const FXlogo: u32 = 0x000000;
const FXlogoWith: i16 = 115;
const FXlogoHeight: i16 = 16;
static mut x: i16 = (WIDTH - FXlogoWith) / 2;
static mut y: i16 = 25;
static mut xDir: i8 = 1;
static mut yDir: i8 = 1;
// The setup() function runs once when you turn your Arduboy on
#[no_mangle]
pub unsafe extern "C" fn setup() {
// put your setup code here, to run once:
arduboy.begin();
arduboy.set_frame_rate(30);
FX::begin_data(FX_DATA_PAGE);
}
// The loop() function repeats forever after setup() is done
#[no_mangle]
@ -38,14 +26,5 @@ pub unsafe extern "C" fn loop_() {
if !arduboy.next_frame() {
return;
}
FX::draw_bitmap(x, y, FXlogo, 0, 0);
x += xDir as i16;
y += yDir as i16;
if x == 0 || x == WIDTH - FXlogoWith {
xDir = -xDir;
}
if y == 0 || y == HEIGHT - FXlogoHeight {
yDir = -yDir;
}
FX::display_clear()
}

View file

@ -50,14 +50,10 @@ extern "C"
{
FX::drawString(buffer);
}
////
void arduboyfx_draw_string(const char *str)
{
FX::drawString(str);
}
////
void arduboyfx_set_cursor_x(int16_t x)
{
FX::setCursorX(x);
@ -80,19 +76,19 @@ extern "C"
}
void arduboyfx_draw_number_i16(int16_t n, int8_t digits)
{
FX::drawNumber(n);
FX::drawNumber(n,digits);
}
void arduboyfx_draw_number_i32(int32_t n, int8_t digits)
{
FX::drawNumber(n);
FX::drawNumber(n,digits);
}
void arduboyfx_draw_number_u16(uint16_t n, int8_t digits)
{
FX::drawNumber(n);
FX::drawNumber(n,digits);
}
void arduboyfx_draw_number_u32(uint32_t n, int8_t digits)
{
FX::drawNumber(n);
FX::drawNumber(n,digits);
}
void arduboyfx_draw_char(uint8_t c)
{

View file

@ -23,6 +23,10 @@ pub const A: ButtonSet = ButtonSet {
pub const B: ButtonSet = ButtonSet {
flag_set: 0b00000100,
};
/// Just a `const` for the any
pub const ANY_BUTTON: ButtonSet = ButtonSet {
flag_set: 0b11111111,
};
/// Just a `const` for the UP button
pub const UP_BUTTON: ButtonSet = UP;
/// Just a `const` for the RIGHT button

View file

@ -4,16 +4,15 @@
//! ```
//! use arduboy_rust::prelude::*;
//!
//! fn setup(){
//! fn setup() {
//! FX::begin()
//! }
//!
//! ```
//! You will need to uncomment the ArduboyFX_Library in the import_config.h file.
#![allow(non_upper_case_globals)]
use super::drawable_number::DrawableNumber;
use super::drawable_string::DrawableString;
use core::ffi::{c_int, c_long, c_size_t, c_uchar, c_uint, c_ulong};
use core::ffi::{c_int, c_size_t, c_uchar, c_uint, c_ulong};
pub fn begin() {
unsafe { arduboyfx_begin() }
}
@ -66,12 +65,15 @@ pub fn set_cursor_x(x: i16) {
pub fn set_cursor_y(y: i16) {
unsafe { arduboyfx_set_cursor_y(y) }
}
pub fn set_cursor_range(left: i32, wrap: i32) {
pub fn set_cursor_range(left: i16, wrap: i16) {
unsafe { arduboyfx_set_cursor_range(left, wrap) }
}
pub fn set_font(address: u32, mode: u8) {
unsafe { arduboyfx_set_font(address, mode) }
}
pub fn set_font_mode(mode: u8) {
unsafe { arduboyfx_set_font_mode(mode) };
}
extern "C" {
#[link_name = "arduboyfx_begin"]
@ -107,8 +109,10 @@ extern "C" {
fn arduboyfx_set_cursor_y(y: c_int);
#[link_name = "arduboyfx_set_font"]
fn arduboyfx_set_font(address: c_ulong, mode: c_uchar);
#[link_name = "arduboyfx_set_font_mode"]
fn arduboyfx_set_font_mode(mode: c_uchar);
#[link_name = "arduboyfx_set_cursor_range"]
fn arduboyfx_set_cursor_range(left: c_long, wrap: c_long);
fn arduboyfx_set_cursor_range(left: c_int, wrap: c_int);
#[link_name = "arduboyfx_draw_char"]
fn arduboyfx_draw_char(c: c_uchar);

View file

@ -11,23 +11,21 @@ pub use crate::hardware::led::{self, *};
pub use crate::heapless::{LinearMap, String, Vec};
pub use crate::library::arduboy2::{self, *};
pub use crate::library::arduboy_tones::{self, ArduboyTones};
#[doc(hidden)]
pub use crate::library::arduboyfx::{self, fx};
pub use crate::library::arduino::*;
pub use crate::library::ardvoice::{self, ArdVoice};
pub use crate::library::c::*;
#[doc(hidden)]
pub use crate::library::arduboyfx::{ fx as FX};
pub use crate::library::arduboyfx::{self};
pub use crate::library::eeprom::{EEPROM, EEPROMBYTE, EEPROMBYTECHECKLESS};
#[doc(hidden)]
pub use crate::library::progmem::Pstring;
pub use crate::library::sprites;
pub use crate::print::*;
#[doc(inline)]
pub use crate::serial_print as serial;
pub use crate::{
f, get_ardvoice_tone_addr, get_sprite_addr, get_string_addr, get_tones_addr, progmem,
};
#[doc(inline)]
pub use crate::{serial_print as serial};
use core::cmp;
pub use core::ffi::{
c_char, c_double, c_float, c_int, c_long, c_longlong, c_size_t, c_uchar, c_uint, c_ulong,

View file

@ -23,6 +23,7 @@ extern "C" {
///
///Example
/// ```
/// use arduboy_rust::prelude::*;
/// let value: i16 = 42;
///
/// serial::print(b"Hello World\n\0"[..]); // Prints "Hello World" and then sets the
@ -42,6 +43,7 @@ pub fn print(x: impl Serialprintable) {
///
///Example
/// ```
/// use arduboy_rust::prelude::*;
/// let value: i16 = 42;
///
/// serial::print(b"Hello World\n\0"[..]); // Prints "Hello World" and then sets the
@ -58,6 +60,7 @@ pub fn println(x: impl Serialprintlnable) {
///
/// ### Example
/// ```
/// use arduboy_rust::prelude::*;
/// serial::begin(9600)
/// ```
pub fn begin(baud_rates: u32) {
@ -69,10 +72,11 @@ pub fn end() {
}
/// Reads incoming serial data.
/// Use only inside of [available()]:
/// ```
/// if (serial::available() > 0) {
///```
/// use arduboy_rust::prelude::*;
/// if serial::available() > 0 {
/// // read the incoming byte:
/// let incoming_byte: i16 = Serial::read();
/// let incoming_byte: i16 = serial::read();
///
/// // say what you got:
/// serial::print("I received: ");
@ -89,23 +93,24 @@ pub fn read() -> i16 {
///
/// Use only inside of [available()]:
/// ```
/// if (Serial::available() > 0) {
/// use arduboy_rust::prelude::*;
/// if serial::available() > 0 {
/// // read the incoming byte:
/// let incomingByte: &str = Serial::read_as_utf8_str();
/// let incoming_byte: &str = serial::read_as_utf8_str();
///
/// // say what you got:
/// Serial::print("I received: ");
/// Serial::println(incomingByte);
/// serial::print("I received: ");
/// serial::println(incoming_byte);
/// }
/// ```
/// ### Returns
///
///The first byte of incoming serial data available (or -1 if no data is available). Data type: &str.
pub fn read_as_utf8_str() -> &'static str {
let intcoming_byte = unsafe { serial_read() };
let incoming_byte = unsafe { serial_read() };
static mut L: [u8; 2] = [0, 0];
unsafe {
L[0] = intcoming_byte as u8;
L[0] = incoming_byte as u8;
}
unsafe { core::str::from_utf8(&L).unwrap() }
}
@ -113,13 +118,14 @@ pub fn read_as_utf8_str() -> &'static str {
/// Get the number of bytes (characters) available for reading from the serial port. This is data thats already arrived and stored in the serial receive buffer (which holds 64 bytes).
/// ### Example
/// ```
/// if (Serial::available() > 0) {
/// use arduboy_rust::prelude::*;
/// if serial::available() > 0 {
/// // read the incoming byte:
/// incomingByte = Serial::read();
/// let incoming_byte = serial::read();
///
/// // say what you got:
/// Serial::print("I received: ");
/// Serial::println(incomingByte);
/// serial::print("I received: ");
/// serial::println(incoming_byte);
/// }
/// ```
pub fn available() -> i16 {
@ -218,7 +224,7 @@ impl Serialprintlnable for &str {
fn default_parameters() -> Self::Parameters {}
}
impl<const N: usize> Serialprintlnable for crate::heapless::String<N> {
impl<const N: usize> Serialprintlnable for heapless::String<N> {
type Parameters = ();
fn println_2(self, _params: Self::Parameters) {
@ -361,7 +367,7 @@ impl Serialprintable for &str {
fn default_parameters() -> Self::Parameters {}
}
impl<const N: usize> Serialprintable for crate::heapless::String<N> {
impl<const N: usize> Serialprintable for heapless::String<N> {
type Parameters = ();
fn print_2(self, _params: Self::Parameters) {

View file

@ -833,7 +833,6 @@
name = name || blob.name || 'download';
a.download = name;
a.rel = 'noopener'; // tabnabbing
// TODO: detect chrome extensions & packaged apps
// a.target = '_blank'
if (typeof blob === 'string') {
@ -1311,7 +1310,6 @@ https://github.com/nodeca/pako/blob/main/LICENSE
/**
* Create the _pako object.
* TODO: lazy-loading this object isn't the best solution but it's the
* quickest. The best solution is to lazy-load the worker list. See also the
* issue #446.
*/
@ -1575,7 +1573,7 @@ https://github.com/nodeca/pako/blob/main/LICENSE
decToHex(encodedComment.length, 2) +
// disk number start
"\x00\x00" +
// internal file attributes TODO
// internal file attributes
"\x00\x00" +
// external file attributes
decToHex(extFileAttr, 4) +
@ -1982,7 +1980,6 @@ https://github.com/nodeca/pako/blob/main/LICENSE
JSZip.support = require("./support");
JSZip.defaults = require("./defaults");
// TODO find a better way to handle this version,
// a require('package.json').version doesn't work with webpack, see #327
JSZip.version = "3.10.1";
@ -2352,7 +2349,6 @@ https://github.com/nodeca/pako/blob/main/LICENSE
var object = new ZipObject(name, zipObjectContent, o);
this.files[name] = object;
/*
TODO: we can't throw an exception because we have async promises
(we can have a promise of a Date() for example) but returning a
promise is useless because file(name, data) returns the JSZip
object for chaining. Should we break that to allow the user
@ -2450,7 +2446,7 @@ https://github.com/nodeca/pako/blob/main/LICENSE
file = this.files[filename];
relativePath = filename.slice(this.root.length, filename.length);
if (relativePath && filename.slice(0, this.root.length) === this.root) { // the file is in the current root
cb(relativePath, file); // TODO reverse the parameters ? need to be clean AND consistent with the filter search fn...
cb(relativePath, file); // reverse the parameters ? need to be clean AND consistent with the filter search fn...
}
}
},
@ -3053,7 +3049,7 @@ https://github.com/nodeca/pako/blob/main/LICENSE
var GenericWorker = require("./GenericWorker");
// the size of the generated chunks
// TODO expose this as a public variable
// expose this as a public variable
var DEFAULT_BLOCK_SIZE = 16 * 1024;
/**
@ -4129,14 +4125,14 @@ https://github.com/nodeca/pako/blob/main/LICENSE
function arrayLikeToString(array) {
// Performances notes :
// --------------------
// String.fromCharCode.apply(null, array) is the fastest, see
// String.fromCharCode.apply(null, array) is the fastest
// see http://jsperf.com/converting-a-uint8array-to-a-string/2
// but the stack is limited (and we can get huge arrays !).
//
// result += String.fromCharCode(array[i]); generate too many strings !
//
// This code is inspired by http://jsperf.com/arraybuffer-to-string-apply-performance/2
// TODO : we now have workers that split the work. Do we still need that ?
// we now have workers that split the work. Do we still need that ?
var chunk = 65536,
type = exports.getTypeOf(array),
canUseApply = true;
@ -9230,7 +9226,6 @@ https://github.com/nodeca/pako/blob/main/LICENSE
this.dmax = 0; /* zlib header max distance (INFLATE_STRICT) */
this.check = 0; /* protected copy of check value */
this.total = 0; /* protected copy of output count */
// TODO: may be {}
this.head = null; /* where to save gzip header information */
/* sliding window */
@ -9762,7 +9757,6 @@ https://github.com/nodeca/pako/blob/main/LICENSE
if (have === 0) { break inf_leave; }
copy = 0;
do {
// TODO: 2 or 1 bytes?
len = input[next + copy++];
/* use constant limit because in js we should not preallocate memory */
if (state.head && len &&

View file

@ -7,7 +7,7 @@
href="https://upload.wikimedia.org/wikipedia/commons/0/0f/Original_Ferris.svg"
type="image/svg+xml"
/>
<title>ZennDev1337 Image Converter</title>
<title>ZennDev1337 fxdata.h Converter</title>
</head>
<body onload="setup(this);">

View file

@ -3,11 +3,15 @@
set option=%1
set optionpath=%2
set folderpath=
if [%optionpath%]==[] (
set optionpath=""
)
if [%option%]==[] (
powershell -Command "cargo build -p game --release; cp ./target/arduboy/release/libgame.a ./arduboy-rust/Wrapper-Project/lib/libgame.a; cd arduboy-rust/Wrapper-Project/; pio run -v -t upload; cp ./.pio/build/arduboy/firmware.hex ./build/game.hex; pio run -t clean; rm lib/libgame.a; cd ../../"
goto :eof
)
if %option%==fxbuild (
for /d /r "./Examples/" %%a in (*) do if /i %%~nxa==%optionpath% (
set folderpath=%%a
@ -19,6 +23,7 @@ if %option%==fxbuild (
)
goto :help
) else if %option%==fxupload (
set optionpath=%2
for /d /r "./Examples/" %%a in (*) do if /i %%~nxa==%optionpath% (
set folderpath=%%a
goto :fxupload
@ -29,6 +34,7 @@ if %option%==fxbuild (
)
goto :help
) else if %option%==fxall (
set optionpath=%2
for /d /r "./Examples/" %%a in (*) do if /i %%~nxa==%optionpath% (
set folderpath=%%a
goto :fxall