diff --git a/README.md b/README.md index d23eaa9..e8025ec 100644 --- a/README.md +++ b/README.md @@ -23,18 +23,15 @@ MicroHydra is a simple MicroPython based app launcher with some OS-like features Microhydra Banner

-*MicroHydra is currently going through a major overhaul to enable multi-platform support. Many features and APIs will likely undergo significant change by version 2.0.* -please use the "releases" section for stable versions of MicroHydra. - This code was built with MicroPython v1.23, for the ESP32-S3. The main function of MicroHydra is to provide an interface to easily switch between MicroPython apps. -And to help lower the barriers to entry for anyone wanting to develop apps for their Cardputer. -Python scripts can be placed in the /apps folder on the flash, or in a /apps folder on a micro sd card. The launcher scans these two locations on startup. +And to help lower the barriers to entry for anyone wanting to develop apps for their Cardputer (or other supported device!). +Python scripts can be placed in your device's /apps folder (on the flash), or in a /apps folder on a micro sd card. The launcher scans these two locations on startup.
-Take a look at the [wiki](https://github.com/echo-lalia/Cardputer-MicroHydra/wiki) for some basic guides to get you started with a MicroPython app. +Take a look at the [wiki](https://github.com/echo-lalia/MicroHydra/wiki) for some basic guides to get you started with a MicroPython app. And for a repository of community-made MicroHydra apps, see [here](https://github.com/echo-lalia/MicroHydra-Apps). @@ -74,77 +71,98 @@ Some apps for MH can be found [here](https://github.com/echo-lalia/MicroHydra-Ap # Installing MicroHydra: -> NOTE: This guide is for MicroHydra 1.x, and will not work for 2.x due to the new way device-specific source files are dynamically created. -> If you want to test out v2.0, check out the preview binaries in the 'releases' section. -> The full 2.x guides will be coming soon :) - You can install MicroHydra a few different ways. - - *Install plain .py version on MicroPython:* - Flash Micropython to your Cardputer, and copy the contents of the "MicroHydra" folder over to the flash. - This is the most convenient way to install for development, because you can simply open up the MH files to see what's going on. - You can also find pre-compiled .mpy versions in "compiled.zip", in the releases section. These will use less memory and start faster. + - [*Install on top of a normal MicroPython installation:*](#In-MicroPython) + Flash Micropython to your Cardputer, and copy the contents of the `DEVICENAME_compiled.zip` (or `DEVICENAME_raw.zip`) file from the "releases" section to the flash on your device. + > This is the most convenient way to install for development, because you can simply open up the MicroHydra files to see what's goin on. However, the `raw` (as in, ending with ".py") form of the software is much more susceptible to memory issues than the other installation methods, so it's reccomended that you use the compiled (`.mpy`) version for any files that you aren't specifically working inside of. + + + + - [*Flash MH as a compiled firmware:*](#As-a-complete-firmware) + You can flash MicroHydra (along with MicroPython) directly to your device using the `DEVICENAME.bin` file from the "Releases" section. (You can also usually find the most recent builds on M5Burner). This is the fastest and easiest to use form of MH! + > In this installation, the MicroHydra files have been 'frozen' into the MicroPython firmware. This makes the built-in files load *much* faster, and makes them all use less memory. + *Make sure you erase the flash before installing, and put your device in download mode by holding G0 when plugging it in.* + +> **Note for developers:** *The contents of `src/` must be processed in order to output device-specific MicroHydra builds. To learn more, take a look at [this](https://github.com/echo-lalia/MicroHydra/wiki/multi-platform) page in the wiki.* + +----- + +

+

+

+

+

+

+ + - - *Flash MH as a compiled firmware:* - The latest 'finished' version of MH, frozen into MicroPython, can be found [here](https://github.com/echo-lalia/microhydra-frozen). (Look for the .bin file in 'releases'.) - This is a form of MicroPython that has MH built in. This is the fastest and easiest to use form of MH - And it can also be downloaded/installed from M5Burner. - This has the drawback of not being able to pick apart or modify the core MH files, however. - *Make sure you erase the flash before installing. Put your device in download mode by holding G0 when plugging it in, if you are having issues* -
-
-**Here's a detailed walkthrough for installing MicroPython, and the ".py" form of MicroHydra:** +# In MicroPython + +*This is a detailed guide for installing MicroHydra on a regular MicroPython installation, using Thonny.* + +

-Download the code from this repository as a zip file, and extract it somewhere on your computer. -*Go to the 'releases' section to get .mpy files, or for a stable checkpoint of MH, if you encounter any issues.* +## Install Thonny -Install Thonny: https://thonny.org/ -*Make sure to use a new version; older versions might fail to flash the ESP32-S3* +Thonny is a tool that provides a very easy way to flash MicroPython, edit code, and view/edit the files on the device. + +You can follow the instructions here to install it: https://thonny.org/ +> *Make sure to use a new version; older versions might fail to flash the ESP32-S3* +> +> *Some sources of Thonny (such as with certain built-in package managers) can result in strange issues with permissions or missing dependencies. If you encounter an issue with thonny when setting it up, and there is no other clear solution to your problem, it might be a good idea to try installing from another source.*


-Open Thonny and click this button in the bottom right: -![image](https://github.com/echo-lalia/Cardputer-MicroHydra/assets/108598670/2464f837-59f0-40d5-860c-52b65d62aa7a) +## Flash MicroPython +Next we need to flash MicroPython on your device + +Open Thonny, click this button in the bottom right, and click "Configure interpreter": +

+ +


-Click "configure interpreter", and it should open this menu: -![image](https://github.com/echo-lalia/Cardputer-MicroHydra/assets/108598670/7a51e32e-9864-4d75-bd43-798e99c9d10a) +It should open this menu: +
click "install or update micropython", and you should see another window: -![image](https://github.com/echo-lalia/Cardputer-MicroHydra/assets/108598670/ef450be6-6025-4bf0-ae0b-e7227209d4ea) +

+ +

-


-Now you need to plug your Cardputer into the computer with USB. You'll probably have to put it into bootloader mode. -To do that, press and hold the G0 button on the Cardputer while you plug it into your PC. -The G0 button is on the back edge of the Cardputer, and there's another G0 button on the [Stamp](https://github.com/echo-lalia/Cardputer-MicroHydra/assets/108598670/2d65ae77-eb1a-4316-b342-690c7b051d25) -
+Now you need to put your device into bootloader mode, and connect it to your computer. To do this, simply hold the `G0` button as you connect it to your PC. + + + +> *You can also hold `G0` and tap the reset button to get to bootloader mode.* +> *If you are using a device like the TDeck, which doesn't power on when plugged in, you must hold `g0` and then flip the power switch on.* +

-In "target port" you should now see a device with a name like "USB JTAG". Set the options in the window like this: -![image](https://github.com/echo-lalia/Cardputer-MicroHydra/assets/108598670/06022ade-a5c3-4b95-be50-d086f963eb6f) -And click Install -*note: version 1.23+ is recommended currently, as it contains an important bugfix affecting MicroHydra's audio* -*You can also flash the MicroHydra Firmware '.bin' from this menu.* +In "target port" you should now see a device with a name like "USB JTAG". Set the options as shown, and click "Install": + +> *For a device with Octal-SPIRAM (like the TDeck), you will have to download a specific Octal-SPIRAM variant from the [MicroPython website.](https://micropython.org/download/ESP32_GENERIC_S3/)* -If installing didn't start, check that the correct device is selected, and it's in bootloader mode. +> *If installing didn't start, check that the correct device is selected, and it's in bootloader mode.*
@@ -162,17 +180,134 @@ If you see something like this in the bottom terminal, you've flashed it success

-To the left in Thonny, there should be a file browser. If there isn't, you need to hit "view">"Files" at the top. -Navigate to the folder where you downloaded this repository, and into the "MicroHydra" folder. Then, select all of the contents, and hit "Upload to /" - -![image](https://github.com/echo-lalia/Cardputer-MicroHydra/assets/108598670/85365da5-1aaf-466c-95b1-76b3fc4f9183) +## Install MicroHydra + +Now you can download and install MicroHydra. +To get the apropriate files for your device, you should head to the "Releases" section of the GitHub page, and look for a `DEVICENAME_compiled.zip` or `DEVICENAME_raw.zip` file. + +

+ +

+ +Extract the .zip file, and head back over to Thonny. + +We need to use Thonnys file browser. If you don't see it to your left, you can bring it up by clicking view>Files in the top left. + + +
+ +On the top half of the file browser, navigate to the folder where you extracted the MicroHydra zip file. +Then, select all of the contents, and hit `Upload to /` +
-Once the files are transferred over to the Cardputer, you can test it out by disconnecting it, and powering it on. If everything is working, you should see the main launcher open up! +Once the files are transferred over, you can test it out by disconnecting it, and powering it on. If everything is working, you should see the main launcher open up! If you have any issues, feel free to reach out. MH is still growing, and I'm interested to hear of any trouble it might be giving you. -

- Demo GIF +---- + +

+

+

+

+

+

+ + + + + + + +# As a complete firmware + +*This is a detailed guide for flashing the MicroHydra firmware on your device, using Thonny.* + +
+
+ +## Install Thonny + +Thonny is a tool that provides a very easy way to flash MicroPython, edit code, and view/edit the files on the device. + +You can follow the instructions here to install it: https://thonny.org/ +> *Make sure to use a new version; older versions might fail to flash the ESP32-S3* +> +> *Some sources of Thonny (such as with certain built-in package managers) can result in strange issues with permissions or missing dependencies. If you encounter an issue with thonny when setting it up, and there is no other clear solution to your problem, it might be a good idea to try installing from another source.* + +
+
+
+ + +## Flash MicroHydra + +Now you can download and install MicroHydra. +To get the apropriate firmware for your device, you should head to the "Releases" section of the GitHub page, look for a `DEVICENAME.bin` file, and download it. + +

+ +

+ +Open Thonny, click this button in the bottom right, and click "Configure interpreter": +

+ +

+ +
+ +It should open this menu: + + + +
+ +click "install or update micropython", and you should see another window: +

+

+ +
+
+ + + + +Now you need to put your device into bootloader mode, and connect it to your computer. To do this, simply hold the `G0` button as you connect it to your PC. + + + +> *You can also hold `G0` and tap the reset button to get to bootloader mode.* +> *If you are using a device like the TDeck, which doesn't power on when plugged in, you must hold `g0` and then flip the power switch on.* + + +
+
+ +Next we will select the firmware .bin file we downloaded. +Click the little menu button and click `Select local MicroPython image ...` + +Navigate to the .bin file you downloaded, and select it. +Make sure you also select your device in the "Target port" dropdown (it should have a name like "USB JTAG"). + +Your window should look something like this: + + +Click "Install", and let it do its thing! + +> *If installing didn't start, check that the correct device is selected, and it's in bootloader mode.* + +Once it's flashed, you can test it out by disconnecting it, and powering it on. If everything is working, you should see the main launcher open up! + +If you have any issues, feel free to reach out. MH is still growing, and I'm interested to hear of any trouble it might be giving you. + +---- + +
+
+
+ + +Demo GIF diff --git a/misc/A_B_speedtesting.py b/misc/A_B_speedtesting.py index 6b84b85..be1fe21 100644 --- a/misc/A_B_speedtesting.py +++ b/misc/A_B_speedtesting.py @@ -2,9 +2,9 @@ import math import random -#this script can easily compare the speed of two functions, to help you write faster code. -#please keep in mind that the order of the tests can affect the results (around 0~10% in my testing). -#you should probably ignore small differences in speed found by this test, but large differences can be super informative. +# this script can easily compare the speed of two functions, to help you write faster code. +# please keep in mind that the order of the tests can affect the results. (around 0~10% usually, in my testing. Sometimes much more.) +# you should be skeptical of the results given by these tests, but large differences can be super informative. oneval = 10 diff --git a/misc/FancyClock.py b/misc/FancyClock.py deleted file mode 100644 index 32febcd..0000000 --- a/misc/FancyClock.py +++ /dev/null @@ -1,358 +0,0 @@ -from lib import st7789py, keyboard, battlevel -from lib import microhydra as mh -from launcher.icons import battery -import time -from font import vga2_16x32 as font -from font import vga1_8x16 as font2 -from machine import SPI, Pin, PWM, reset -import machine -import random - -max_bright = const(65535) -min_bright = const(22000) -bright_peak = const(65535) -bright_step = const(500) - - -# v1.2 -# a simple clock program for the cardputer - - -tft = st7789py.ST7789( - SPI(1, baudrate=40000000, sck=Pin(36), mosi=Pin(35), miso=None), - 135, - 240, - reset=Pin(33, Pin.OUT), - cs=Pin(37, Pin.OUT), - dc=Pin(34, Pin.OUT), - backlight=None, #because we will control that manually - rotation=1, - color_order=st7789py.BGR - ) - - - - - -blight = PWM(Pin(38, Pin.OUT)) -blight.freq(1000) -blight.duty_u16(bright_peak) - - -tft.fill_rect(-40,0,280, 135, 0) - -months_names = { - 1:'Jan', - 2:'Feb', - 3:'Mar', - 4:'Apr', - 5:'May', - 6:'Jun', - 7:'Jul', - 8:'Aug', - 9:'Sep', - 10:'Oct', - 11:'Nov', - 12:'Dec' - } - - -def hsv_to_rgb(HSV): - ''' Converts an integer HSV tuple (value range from 0 to 255) to an RGB tuple ''' - - # Unpack the HSV tuple for readability - H, S, V = HSV - - # Check if the color is Grayscale - if S == 0: - R = V - G = V - B = V - return (R, G, B) - - # Make hue 0-5 - region = H // 43; - - # Find remainder part, make it from 0-255 - remainder = (H - (region * 43)) * 6; - - # Calculate temp vars, doing integer multiplication - P = (V * (255 - S)) >> 8; - Q = (V * (255 - ((S * remainder) >> 8))) >> 8; - T = (V * (255 - ((S * (255 - remainder)) >> 8))) >> 8; - - - # Assign temp vars based on color cone region - if region == 0: - R = V - G = T - B = P - elif region == 1: - R = Q; - G = V; - B = P; - elif region == 2: - R = P; - G = V; - B = T; - elif region == 3: - R = P; - G = Q; - B = V; - elif region == 4: - R = T; - G = P; - B = V; - else: - R = V; - G = P; - B = Q; - - return (R, G, B) - - -def get_random_colors(): - #main hue - hue1 = random.randint(0,255) - #bg hue - hue2 = hue1 + random.randint(-80,80) - - sat1 = random.randint(0,255) - sat2 = random.randint(50,255) - - - val1 = random.randint(245,255) - val2 = random.randint(10,20) - - - - #convert to color565 - ui_color = st7789py.color565(hsv_to_rgb((hue1,sat1,val1))) - bg_color = st7789py.color565(hsv_to_rgb((hue2,sat2,val2))) - lighter_color = st7789py.color565(hsv_to_rgb((hue2,max(sat2 - 5, 0),val2 + 8))) - darker_color = st7789py.color565(hsv_to_rgb((hue2,min(sat2 + 60, 255),max(val2 - 4,0)))) - - #get middle hue - mid_color = mh.mix_color565(bg_color, ui_color) - - return ui_color, bg_color, mid_color, lighter_color, darker_color - - -kb = keyboard.KeyBoard() - -moving_right = True #horizontal movement -moving_up = False #vertical movement - -x_pos = 50 -y_pos = 50 - -#random color -ui_color, bg_color, mid_color, lighter_color, darker_color = get_random_colors() -red_color = mh.color565_shiftred(mid_color) - -old_minute = 0 - -prev_pressed_keys = kb.get_pressed_keys() -current_bright = bright_peak - -#init the ADC for the battery -batt = battlevel.Battery() -batt_level = batt.read_level() - - - -#we can slightly speed up the loop by only doing some calculations every x number of frames -loop_timer = 0 - -#init vals for loop timer stuff: -_, month, day, hour_24, minute, _,_,_ = time.localtime() -hour_12 = hour_24 % 12 -if hour_12 == 0: - hour_12 = 12 -ampm = 'AM' -if hour_24 >= 12: - ampm = 'PM' -time_string = f"{hour_12}:{'{:02d}'.format(minute)}" -date_string = f"{months_names[month]},{day}" -time_width = len(time_string) * 16 -date_width = len(date_string) * 8 -batfill_total_width = (time_width + 16) - (date_width + 4) - - -while True: - - #loop timer stuff; only update every x number of frames - if loop_timer > 100: - loop_timer = 0 - - _, month, day, hour_24, minute, _,_,_ = time.localtime() - - hour_12 = hour_24 % 12 - if hour_12 == 0: - hour_12 = 12 - - ampm = 'AM' - if hour_24 >= 12: - ampm = 'PM' - - time_string = f"{hour_12}:{'{:02d}'.format(minute)}" - date_string = f"{months_names[month]},{day}" - time_width = len(time_string) * 16 - date_width = len(date_string) * 8 - - batfill_total_width = (time_width + 16) - (date_width + 4) - - else: - loop_timer += 1 - - - - #add main graphics first - tft.text( - font, - time_string, - x_pos, - y_pos, - ui_color, bg_color) - tft.text( - font2, - ampm, - time_width + x_pos,16 + y_pos, - mid_color, bg_color) - - #date - tft.fill_rect(x_pos,y_pos + 32, 4, 16, bg_color) - tft.text( - font2, - date_string, - x_pos + 4, - y_pos + 32, - mid_color, bg_color) - - - - # extract useful positions for fill section - battfill_x = x_pos + date_width + 4 - battfill_y = y_pos + 32 - batt_x = x_pos + time_width - 8 - - - - # battery - - if batt_level == 3: - tft.bitmap_icons(battery, battery.FULL, (bg_color,mid_color),batt_x, y_pos + 34) - elif batt_level == 2: - tft.bitmap_icons(battery, battery.HIGH, (bg_color,mid_color),batt_x, y_pos + 34) - elif batt_level == 1: - tft.bitmap_icons(battery, battery.LOW, (bg_color,mid_color),batt_x, y_pos + 34) - elif batt_level == 0: - tft.bitmap_icons(battery, battery.EMPTY, (bg_color,red_color),batt_x, y_pos + 34) - - - - #the spot beside the date and battery - #we have to fill AROUND the battery to prevent a flashy/glitchy display - tft.fill_rect(battfill_x, battfill_y, batfill_total_width , 2, bg_color) #line above - tft.fill_rect(battfill_x, battfill_y + 12, batfill_total_width , 4, bg_color) #line below - tft.fill_rect(batt_x + 20, battfill_y + 2, 4 , 10, bg_color) #box right - tft.fill_rect(battfill_x, battfill_y + 2, batfill_total_width - 24, 10, bg_color) #box left - - - - #cover up the little spot above the am/pm - tft.fill_rect(x_pos + time_width, y_pos, 16, 16, bg_color) - - - - #add a line to the right to pad the am/pm a little - tft.fill_rect(x_pos + time_width + 16, y_pos, 2, 49, bg_color) - #and a line to the left to frame the time better - tft.fill_rect(x_pos-2, y_pos, 2, 49, bg_color) - - - - #highlight/shadow - tft.hline(x_pos-2, y_pos-1, time_width + 20, lighter_color) - tft.hline(x_pos-2, y_pos+48, time_width + 20, darker_color) - - - if moving_right: - x_pos += 1 - else: - x_pos -= 1 - - if moving_up: - y_pos -= 1 - else: - y_pos +=1 - - - #y_collision - if y_pos <= 1: - y_pos = 1 - moving_up = False - ui_color, bg_color, mid_color, lighter_color, darker_color = get_random_colors() - red_color = mh.color565_shiftred(mid_color) - batt_level = batt.read_level() - - elif y_pos >= 87: - y_pos = 87 - moving_up = True - ui_color, bg_color, mid_color, lighter_color, darker_color = get_random_colors() - red_color = mh.color565_shiftred(mid_color) - batt_level = batt.read_level() - - - #x_collision - if x_pos <= 0: - x_pos = 0 - moving_right = True - ui_color, bg_color, mid_color, lighter_color, darker_color = get_random_colors() - red_color = mh.color565_shiftred(mid_color) - batt_level = batt.read_level() - - elif x_pos >= 224 - time_width: - x_pos = 224 - time_width - moving_right = False - ui_color, bg_color, mid_color, lighter_color, darker_color = get_random_colors() - red_color = mh.color565_shiftred(mid_color) - batt_level = batt.read_level() - - - - - #refresh bg on 5 mins - if minute != old_minute and minute % 5 == 0: - old_minute = minute - tft.fill(0) - - #keystrokes and backlight - pressed_keys = kb.get_pressed_keys() - if pressed_keys != prev_pressed_keys: # some button has been pressed - if "GO" in pressed_keys: - tft.fill(0) - tft.sleep_mode(True) - blight.duty_u16(0) - reset() - current_bright = bright_peak - elif current_bright != min_bright: - current_bright -= bright_step - if current_bright < min_bright: - current_bright = min_bright - blight.duty_u16(min(max_bright,current_bright)) - - - prev_pressed_keys = pressed_keys - - if "SPC" in pressed_keys: - current_bright = bright_peak - time.sleep_ms(1) - else: - time.sleep_ms(70) - - - - - - diff --git a/misc/attr.txt b/misc/attr.txt deleted file mode 100644 index ddfa84a..0000000 --- a/misc/attr.txt +++ /dev/null @@ -1,3 +0,0 @@ -Display driver and font support | MIT License: https://github.com/russhughes/st7789py_mpy/tree/master - -RGB-HSV conversions: | PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2 : https://github.com/python/cpython/tree/3.12?tab=License-1-ov-file \ No newline at end of file diff --git a/misc/beeper.OLD.py b/misc/beeper.OLD.py deleted file mode 100644 index a5064b6..0000000 --- a/misc/beeper.OLD.py +++ /dev/null @@ -1,161 +0,0 @@ -from machine import I2S, Pin -import time -import math - - -#This is a simple sound module that uses pre-generated sin-waves for quickly playing short ui beeps. -#The sound quality from this module could probably be improved, especially because the results seem to be out of tune. However, for now, this works well for simple UI beeps. - -# one loop of a sin wave. #25hz -fast_sin = const(b'\x7f\x7f\x83\x83\x88\x88\x8d\x8d\x92\x92\x97\x97\x9c\x9c\xa1\xa1\xa6\xa6\xaa\xaa\xaf\xaf\xb4\xb4\xb8\xb8\xbd\xbd\xc1\xc1\xc5\xc5\xc9\xc9\xcd\xcd\xd1\xd1\xd5\xd5\xd8\xd8\xdc\xdc\xdf\xdf\xe2\xe2\xe5\xe5\xe8\xe8\xeb\xeb\xed\xed\xf0\xf0\xf2\xf2\xf4\xf4\xf6\xf6\xf7\xf7\xf9\xf9\xfa\xfa\xfb\xfb\xfc\xfc\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfc\xfc\xfb\xfb\xfa\xfa\xf9\xf9\xf7\xf7\xf6\xf6\xf4\xf4\xf2\xf2\xf0\xf0\xed\xed\xeb\xeb\xe8\xe8\xe5\xe5\xe2\xe2\xdf\xdf\xdc\xdc\xd8\xd8\xd5\xd5\xd1\xd1\xcd\xcd\xc9\xc9\xc5\xc5\xc1\xc1\xbd\xbd\xb8\xb8\xb4\xb4\xaf\xaf\xaa\xaa\xa6\xa6\xa1\xa1\x9c\x9c\x97\x97\x92\x92\x8d\x8d\x88\x88\x83\x83~~zzuuppkkffaa\\\\WWSSNNIIEE@@<<884400,,((%%!!\x1e\x1e\x1b\x1b\x18\x18\x15\x15\x12\x12\x10\x10\r\r\x0b\x0b\t\t\x07\x07\x06\x06\x04\x04\x03\x03\x02\x02\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x01\x02\x02\x03\x03\x04\x04\x06\x06\x07\x07\t\t\x0b\x0b\r\r\x10\x10\x12\x12\x15\x15\x18\x18\x1b\x1b\x1e\x1e!!%%((,,004488<<@@EEIINNSSWW\\\\aaffkkppuuzz') - -greensleeves = const('A4 A4 C5 C5 C5 C5 D5 D5 E5 E5 E5 E5 F5 E5 D5 D5 D5 D5 B4 B4 G4 G4 G4 G4 A4 B4 C5 C5 C5 C5 A4 A4 A4 A4 GS4 GS4 A4 A4 B4 B4 B4 B4 - GS4 GS4 E4 E4 E4 E4 A4 A4 C5 C5 C5 C5 D5 D5 E5 E5 E5 E5 F5 E5 D5 D5 D5 D5 B4 B4 G4 G4 G4 G4 A4 B4 C5 C5 B4 B4 A4 A4 GS4 GS4 - FS4 FS4 - GS4 GS4 - A4 A4 A4 A4 A4 A4 - A4 A4 A4 A4 A4 A4 - G5 G5 G5 G5 - G5 G5 G5 G5 - FS5 E5 D5 D5 D5 D5 - B4 B4 G4 G4 G4 G4 A4 B4 C5 C5 C5 C5 - A4 A4 - A4 A4 GS4 GS4 A4 A4 B4 B4 B4 B4 GS4 GS4 E4 E4 E4 E4 - G5 G5 G5 G5 - G5 G5 G5 G5 - FS5 E5 D5 D5 D5 D5 - B4 B4 G4 G4 G4 G4 A4 B4 C5 C5 - B4 B4 - A4 A4 - GS4 GS4 - FS4 FS4 - - GS4 GS4 - - - A4 A4 A4 A4 A4 A4 - - A4 A4 A4 A4 A4 A4') - -fast_sin_len = const(320) -fast_sin_hz = const(25) -SCK_PIN = const(41) -WS_PIN = const(43) -SD_PIN = const(42) -I2S_ID = const(1) -BUFFER_LENGTH_IN_BYTES = const(4000) -SAMPLE_SIZE_IN_BITS = const(16) -FORMAT = I2S.STEREO -SAMPLE_RATE_IN_HZ = const(8000) - -tone_map = { -"C3": 131, -"CS3": 139, -"D3": 147, -"DS3": 156, -"E3": 165, -"F3": 175, -"FS3": 185, -"G3": 196, -"GS3": 208, -"A3": 220, -"AS3": 233, -"B3": 247, -"C4": 262, -"CS4": 277, -"D4": 294, -"DS4": 311, -"E4": 330, -"F4": 349, -"FS4": 370, -"G4": 392, -"GS4": 415, -"A4": 440, -"AS4": 466, -"B4": 494, -"C5": 523, -"CS5": 554, -"D5": 587, -"DS5": 622, -"E5": 659, -"F5": 698, -"FS5": 740, -"G5": 784, -"GS5": 831, -"A5": 880, -"AS5": 932, -"B5": 988, -"C6": 1047, -"CS6": 1109, -"D6": 1175, -"-":4000 -} - - - - -# Beeper object controlls your access to the i2s module, and keeps track of what's playing -class Beeper: - #TODO: fix the pitch issues with the outputs generated by this class. - - def __init__(self): - - self._output = I2S( - I2S_ID, - sck=Pin(SCK_PIN), - ws=Pin(WS_PIN), - sd=Pin(SD_PIN), - mode=I2S.TX, - bits=SAMPLE_SIZE_IN_BITS, - format=FORMAT, - rate=SAMPLE_RATE_IN_HZ, - ibuf=BUFFER_LENGTH_IN_BYTES) - - self._current_notes = [] - - self._mv = memoryview(fast_sin) - - self._buf = bytearray(1000) - self._buf_mv = memoryview(self._buf) - def __del__(self): - self._output.deinit() - - def fast_sin_gen(self, freq, length_seconds=0.1, volume_shift=-2): - ''' - generate a frequency from the pre-generated fast sin constant. - Recommended value range for volume shift: -7 to 2. -8 essentialy mutes it. - frequencies less than than 8hz will raise an error - ''' - - - sample_length_bytes = math.floor(SAMPLE_RATE_IN_HZ * length_seconds) # "* 2" because its 16 bit audio - - #how many times the fast sin must loop in our sample: - times_to_loop = math.floor(freq * length_seconds) - - sample_length_bytes_once = sample_length_bytes // times_to_loop - speed_multiplier = freq / fast_sin_hz - - if volume_shift < 0: - for i in range(0,sample_length_bytes_once): - self._buf[i] = self._mv[math.floor(i * speed_multiplier) % fast_sin_len] >> abs(volume_shift) - else: - for i in range(0,sample_length_bytes_once): - self._buf[i] = self._mv[math.floor(i * speed_multiplier) % fast_sin_len] << volume_shift - - #print(self._buf[:sample_length_bytes_once]) - for i in range(0,times_to_loop): - self._output.write(self._buf_mv[:sample_length_bytes_once]) - - def play(self, notes, length_seconds=0.1, volume=4): - ''' - Play given notes for given duration, and of given volume. - volume is an int value from 0 to 10. - notes should be a string containing one or more notes separated by spaces. - ''' - if not 0 <= volume <= 10: - raise ValueError(f"beep.play got a volume of {volume}, but it should be an int between 0 and 10.") - notes = notes.split() - for note in notes: - self.fast_sin_gen( - freq=tone_map[note], - length_seconds=length_seconds, - volume_shift=volume - 7 - ) - - -def gen_sin_wave(freq, volume=1): - # I dont trust this guy. - radians_increment = (math.pi / SAMPLE_RATE_IN_HZ) * freq - - samples = bytearray() - rads_current = 0 - while rads_current < (math.pi * 2): - sample = math.floor(math.sin(rads_current) * 127) + 127 - samples += bytearray((sample, sample)) - rads_current += radians_increment - return samples - - -if __name__ == "__main__": - beep = Beeper() - # I imported a greensleeves string I made for another project, and it sounds pretty rough, haha. - # The timing needs to be fixed, but worse is that the notes are super out of tune. Sounds better out of PWM. - #beep.play(geensleeves, length_seconds=0.2, volume=1) - beep = Beeper() - beep.play('C4 B4 C5 C5',0.14,2) - del beep diff --git a/misc/clock.py b/misc/clock.py deleted file mode 100644 index 535e607..0000000 --- a/misc/clock.py +++ /dev/null @@ -1,168 +0,0 @@ -from lib import st7789py -import time -from font import vga2_16x32 as font -from font import vga1_8x16 as font2 -from machine import SPI, Pin, PWM -import random - -#a simple clock program for the cardputer - - - -tft = st7789py.ST7789( - SPI(1, baudrate=40000000, sck=Pin(36), mosi=Pin(35), miso=None), - 135, - 240, - reset=Pin(33, Pin.OUT), - cs=Pin(37, Pin.OUT), - dc=Pin(34, Pin.OUT), - backlight=Pin(38, Pin.OUT), #because we will controll that manually - rotation=1, - color_order=st7789py.BGR - ) - - - - - - - - -def hsv_to_rgb(HSV): - ''' Converts an integer HSV tuple (value range from 0 to 255) to an RGB tuple ''' - - # Unpack the HSV tuple for readability - H, S, V = HSV - - # Check if the color is Grayscale - if S == 0: - R = V - G = V - B = V - return (R, G, B) - - # Make hue 0-5 - region = H // 43; - - # Find remainder part, make it from 0-255 - remainder = (H - (region * 43)) * 6; - - # Calculate temp vars, doing integer multiplication - P = (V * (255 - S)) >> 8; - Q = (V * (255 - ((S * remainder) >> 8))) >> 8; - T = (V * (255 - ((S * (255 - remainder)) >> 8))) >> 8; - - - # Assign temp vars based on color cone region - if region == 0: - R = V - G = T - B = P - elif region == 1: - R = Q; - G = V; - B = P; - elif region == 2: - R = P; - G = V; - B = T; - elif region == 3: - R = P; - G = Q; - B = V; - elif region == 4: - R = T; - G = P; - B = V; - else: - R = V; - G = P; - B = Q; - - return (R, G, B) - - - - - - - - - - -#main body: - - -#backlight.duty_u16(50000) - -moving_right = True #horizontal movement -moving_up = False #vertical movement - -x_pos = 0 -y_pos = 0 - -#random color -r, g, b = hsv_to_rgb((random.randint(0,255), random.randint(0,255), 255)) - -while True: - - _,_,_, hour_24, minute, _,_,_ = time.localtime() - - hour_12 = hour_24 % 12 - if hour_12 == 0: - hour_12 = 12 - - ampm = 'AM' - if hour_24 >= 12: - ampm = 'PM' - - time_string = f"{hour_12}:{'{:02d}'.format(minute)}" - time_width = len(time_string) * 16 - - - - tft.text( - font, - time_string, - x_pos, - y_pos, - st7789py.color565(r,g,b)) - tft.text( - font2, - f'{ampm}', - time_width + x_pos,16 + y_pos, - st7789py.color565(r//2,g//2,b//2)) - - if moving_right: - x_pos += 1 - else: - x_pos -= 1 - - if moving_up: - y_pos -= 1 - else: - y_pos +=1 - - - #y_collision - if y_pos <= 0: - y_pos = 0 - moving_up = False - r,g,b = hsv_to_rgb((random.randint(0,255), random.randint(0,255), 255)) - - elif y_pos >= 103: - y_pos = 103 - moving_up = True - r,g,b = hsv_to_rgb((random.randint(0,255), random.randint(0,255), 255)) - - #x_collision - if x_pos <= 0: - x_pos = 0 - moving_right = True - r,g,b = hsv_to_rgb((random.randint(0,255), random.randint(0,255), 255)) - elif x_pos >= 224 - time_width: - x_pos = 224 - time_width - moving_right = False - r,g,b = hsv_to_rgb((random.randint(0,255), random.randint(0,255), 255)) - - time.sleep(0.05) diff --git a/misc/images/cardputerg0.jpg b/misc/images/cardputerg0.jpg new file mode 100644 index 0000000..c682b00 Binary files /dev/null and b/misc/images/cardputerg0.jpg differ diff --git a/misc/images/releasebin.png b/misc/images/releasebin.png new file mode 100644 index 0000000..31475fd Binary files /dev/null and b/misc/images/releasebin.png differ diff --git a/misc/images/releasecompiled.png b/misc/images/releasecompiled.png new file mode 100644 index 0000000..f265c28 Binary files /dev/null and b/misc/images/releasecompiled.png differ diff --git a/misc/images/releases.png b/misc/images/releases.png new file mode 100644 index 0000000..3221409 Binary files /dev/null and b/misc/images/releases.png differ diff --git a/misc/images/thonnyconfigureinterpreter.png b/misc/images/thonnyconfigureinterpreter.png new file mode 100644 index 0000000..d316020 Binary files /dev/null and b/misc/images/thonnyconfigureinterpreter.png differ diff --git a/misc/images/thonnyfiles.png b/misc/images/thonnyfiles.png new file mode 100644 index 0000000..56ad16e Binary files /dev/null and b/misc/images/thonnyfiles.png differ diff --git a/misc/images/thonnyflashbin.png b/misc/images/thonnyflashbin.png new file mode 100644 index 0000000..ac2d892 Binary files /dev/null and b/misc/images/thonnyflashbin.png differ diff --git a/misc/images/thonnyflashsettings.png b/misc/images/thonnyflashsettings.png new file mode 100644 index 0000000..acb7f1b Binary files /dev/null and b/misc/images/thonnyflashsettings.png differ diff --git a/misc/images/thonnyhamburgermenu.png b/misc/images/thonnyhamburgermenu.png new file mode 100644 index 0000000..b1c2e9c Binary files /dev/null and b/misc/images/thonnyhamburgermenu.png differ diff --git a/misc/images/thonnyinstallmicropython.png b/misc/images/thonnyinstallmicropython.png new file mode 100644 index 0000000..aef888d Binary files /dev/null and b/misc/images/thonnyinstallmicropython.png differ diff --git a/misc/images/thonnyinstallmicropythonwindow.png b/misc/images/thonnyinstallmicropythonwindow.png new file mode 100644 index 0000000..2ae37d3 Binary files /dev/null and b/misc/images/thonnyinstallmicropythonwindow.png differ diff --git a/misc/images/thonnyinterpreteroptions.png b/misc/images/thonnyinterpreteroptions.png new file mode 100644 index 0000000..250181c Binary files /dev/null and b/misc/images/thonnyinterpreteroptions.png differ diff --git a/misc/images/thonnylocalmicropython.png b/misc/images/thonnylocalmicropython.png new file mode 100644 index 0000000..93837be Binary files /dev/null and b/misc/images/thonnylocalmicropython.png differ diff --git a/misc/images/thonnyuploadfiles.png b/misc/images/thonnyuploadfiles.png new file mode 100644 index 0000000..2d7425a Binary files /dev/null and b/misc/images/thonnyuploadfiles.png differ diff --git a/misc/images/thonnyuploadfiles2.png b/misc/images/thonnyuploadfiles2.png new file mode 100644 index 0000000..4231f4d Binary files /dev/null and b/misc/images/thonnyuploadfiles2.png differ diff --git a/misc/launchappfromSD.py b/misc/launchappfromSD.py deleted file mode 100644 index 65ad40a..0000000 --- a/misc/launchappfromSD.py +++ /dev/null @@ -1,34 +0,0 @@ -import os -import machine -from machine import RTC, SDCard, Pin - -""" -This simple tool can be used for importing an app from the SD card (or anywhere else) just like the app loader in main.py does. -Good for testing and debugging app behaviour on SDCard apps especially. - -""" - - -# app to launch from SD -app_path = "/sd/apps/displaytest.py" - - - - -sd = SDCard(slot=2, sck=Pin(40), miso=Pin(39), mosi=Pin(14), cs=Pin(12)) -try: - os.mount(sd, '/sd') -except OSError as e: - print(e) - print("Could not mount SDCard!") - - - - -try: - __import__(app_path) -except ImportError as e: - print(e) - print(f"Tried to launch {app_path}, but failed!") - - \ No newline at end of file diff --git a/misc/mountSD.py b/misc/mountSD.py index 324ca3f..25ebf3c 100644 --- a/misc/mountSD.py +++ b/misc/mountSD.py @@ -1,5 +1,4 @@ -import os -from machine import RTC, SDCard, Pin +from lib.sdcard import SDCard """ Use this simple tool to mount your SD card. This is useful for transferring files via USB and for editing apps on the SD card. @@ -10,14 +9,5 @@ """ - - - - - -sd = SDCard(slot=2, sck=Pin(40), miso=Pin(39), mosi=Pin(14), cs=Pin(12)) -try: - os.mount(sd, '/sd') -except OSError as e: - print(e) - print("Could not mount SDCard!") \ No newline at end of file +sd = SDCard() +sd.mount() diff --git a/misc/unmountSD.py b/misc/unmountSD.py deleted file mode 100644 index 05f3d38..0000000 --- a/misc/unmountSD.py +++ /dev/null @@ -1,24 +0,0 @@ -import os -from machine import RTC, SDCard, Pin - -""" -Use this simple tool to unmount your SD card. -Not sure if this one is actually useful, but I thought I'd provide it for completion sake. - - -""" - - - - -try: - sd = SDCard(slot=2, sck=Pin(40), miso=Pin(39), mosi=Pin(14), cs=Pin(12)) - sd.deinit() -except: - print("couldn't deinit SDCard") - -try: - os.umount('/sd') -except OSError as e: - print(e) - print("Could not unmount SDCard!") diff --git a/tools/image_to_icon.py b/tools/icons/image_to_icon.py similarity index 100% rename from tools/image_to_icon.py rename to tools/icons/image_to_icon.py diff --git a/tools/polygon_to_raw_bmp.py b/tools/icons/polygon_to_raw_bmp.py similarity index 100% rename from tools/polygon_to_raw_bmp.py rename to tools/icons/polygon_to_raw_bmp.py diff --git a/wiki/App-Format.md b/wiki/App-Format.md index 7debf40..0a5d177 100644 --- a/wiki/App-Format.md +++ b/wiki/App-Format.md @@ -27,13 +27,13 @@ except: ## App Icons: > Quick note: -> *The previous version of MicroHydra used a bizzare method of packing vectorized/polygonal icon definitions into a short string, which would be unpacked and executed by the launcher. This strategy was chosen for memory efficiency, but it felt awkward and is not used anymore. The script `polygon_to_raw_bmp.py` from the tools folder has been written to convert these old polygon defs if needed.* +> *The previous version of MicroHydra used a bizzare method of packing vectorized/polygonal icon definitions into a short string, which would be unpacked and executed by the launcher. This strategy was chosen for memory efficiency, but it felt awkward and is not used anymore. The script `polygon_to_raw_bmp.py` from the `tools/icons` folder has been written to convert these old polygon defs if needed.*
**To put it simply:** MicroHydra app icons are 32x32, 1bit, raw bitmaps (not bmp files) named `icon.raw`. Your app icon should be placed in the main directory of your app, alongside the `__init__.py` file. -You can simply create these files using the `image_to_icon.py` file in the "tools" folder. +You can simply create these files using the `image_to_icon.py` file in the `tools/icons` folder.