-
Hacking the DF-Player Mini
09/15/2018 at 19:50 • 0 commentsSince I am still waiting for the PCBs for the new SDA, I turned my attention to the DFPlayer mini module.
I use it almost daily to listen music from my PDA and it needed some improvements.Into the DFPlayer
File names
If you used DFPlayer, you know that the filenames of sound files must be named "001.mp3" "002.mp3" and so on, then copied to the SD card and then you can play them by their number.
One would think that the DFPlayer reads the file names but that is not true. When you copy mp3 files with any name, it will still happily play them, but you do not know the order. Truth is, that you need to rename the files, so they got copied in the right order, because DFPlayer does not read the names, it simply lists the directory. And if you do directory listing, you get files in the order filesystem throws them at you. You can do this with a simple shell command:find . -maxdepth 1 -name '*.mp3'
Now I can index the files in the order the DFPlayer will read them and store the index in my PDA. With the index, I can view the file names and play the songs on demand.
Playback status
There is still a problem, that I don't know when the DFPlayer stopped its playback. Option one is to read the "busy" pin on the player, but I am out of pins in my expansion port. Second option is to send some message to the player that will give me its status. That is nice, but serial receive API on my PDA is still a bit wonky. Third option is to index duration of the mp3 files when indexing the file names. Then the PDA can wait for the song to stop playing and send command to play next song, while updating the "currently played" information.
I ended up with this:
It lists the files, creates command queue with AWK, pipes it to bash and outputs it to my database file. In the future I can also read and index id3 tags this way.find . -maxdepth 1 -name '*.mp3' \ | awk 'BEGIN{ a=0 }{ printf "echo \"%d=%s\" & mp3info -p \"%d_len=%%S\\n\" \"%s\" \n", a, substr($0,3),a, substr($0,3), a++ }' \ | bash > mp3-list.dat
Random playback
Last thing that is a bit weird on the DFPlayer is its random playback feature. It is too much random. Imagine you have thirty songs, when the player is choosing what song to play, it does something like play_song(random() % 31). On the first glance this seem right, but fire up random number generator of your choice and try it. You end up repeating one song quite often and that's not what you want from random playback. You need at least to check for repetition and perform another random throw when it happens.
This is the end result, the new player has smarter random playback, you can select the songs by their name (yes, they are still numbered in the screens, but it works with any name, trust me;) and it will show you the current song and position in the song.
Conclusion
Index your SD Card if you want to step-up your DFPlayer game. It is simple and efficient.
-
Short update on the software
09/09/2018 at 22:20 • 0 commentsFor the past half a year I was mostly working on the software. There are few new software features and the simplest way to show them was to make an update video.
Task switching
The largest new feature is task switching. It is only task switching and not multitasking, only one application is running at any given time. I made some modifications to the graphics library and the application runtime so the full state of a running application can be stored on the SD card. When tasks are switched, the currently running task is stored and the new task is launched or restored.
New applications
There are few new apps, most of them were described in previous logs (MP3 Player, GPS, snake), but there are also few new ones. SDA Commander is a simple file manager, it can browse folders, edit text files, show pictures and run executables (SVS scripts). I also met one of the design milestones and that is self-programmability of the PDA. It is not very usefull for now (it is limited to about 1kb of code), but as a proof-of concept it works. I had some problems typing in the video and that is mostly because I was looking on the PDA through the camera viewfinder.
Also the overall system stability was improved, in the first video I had to reset the device at the start of each take to get consistent results. Here I just picked up the PDA, did the demo and everything worked without a glitch while the system was running for about fourteen days with four hours of screen on time.
Since I am waiting for the PCBs to continue with the next design iteration of the hardware I am refactoring the code and writing some basic documentation for the SDA_OS github repo that will be up in a few weeks.
-
Short update on new hardware
09/04/2018 at 22:16 • 3 commentsI am still working on my PDA. I have some software updates, but I will make a separate video about that in the future.
The main thing is that I am finally designing new version of the hardware.
Main features of the new PDA:
- It will have a fancy PCB.
- The new 3D printed case will not need too much hand fitting after print.
- It will all hold together with screws instead of hot glue and duct tape.
- It will use BL-5C nokia battery.
It looks very similar to the previous PDA, but I mostly redesigned the hardware from scratch. Software will be mostly the same. Now I am in the phase of verifying the design and I will open-source it after I will have a working prototype.
The PCB is still work in progress, All the SMD components are on one side, so they eventually can be placed by machine and soldered with reflow, the board will still need a bit of hand soldering and some fitting of a few THT components.
-
Addon Addendum
07/03/2018 at 13:44 • 2 commentsDFPlayer Mini module and the SDA
I saw some projects that were using this module, so I also gave it a try. And the result?
I'd buy that for a dollar!
Basically DFPlayer Mini is the ESP 8266 of MP3 playback. It is MP3 player in one small module, it can play audio files (mp3, wav) from its SD card (or USB flash drive) directly to your headphones. Module can be controlled over its serial interface or directly with buttons. There are some limitations, like that the player needs specific file structure and file naming on the storage media and somewhat poor documentation. There are few arduino libraries for it and the protocol is simple.
Getting it running
After a bit of struggle with error code 04, that was not mentioned in a datasheet that I had, I googled a bit and found datasheet for the FN-M22P Embedded MP3 Audio Module which looks like it is using the same protocol as DFPlayer. Datasheet for FN-M22P actually mentions all error codes and is written in normal English. The only difference between the FN-M22P and DFPlayer I found is that the DFPlayer does not support commands without checksum (but I did not try everything).
Hardware is held inside improved version of the addon case used in the GPS module. It is more sturdy and holds better on the PDA. Inside there is just the DFPlayer with its DAC pins connected to 3.5 jack. Its control app is written in 120 lines of SVS. It is quite limited in its functionality and it has no idea what is the state of the module. It is good for now but there is also space for some improvements.
Performance
The DFPlayer just works enough to be usefull. You do not have much control over the playback, you can't read metadata from the songs or do anything with the files. In my case the sound quality is good but not great, there is always a quiet hiss that can be heard if you focus on it. It could come from power supply of my PDA, but I don't have the equipment to pinpoint source of that distortion.
-
Lets make some add-ons
06/16/2018 at 21:43 • 0 commentsExtensible PDAs of the past
Every old Palm PDA had a serial port on its docking connector. It was mostly used for synchronizing data with a PC, but the port was user accessible and used for many hardware add-ons (like keyboards, digital cameras, mp3 players, bar-code readers, modems etc.). Handspring devices went even further with hardware extensibility and introduced springboards, these modules also doubled as software cartridges. If you had, for example the camera module, you just pushed it in your PDA and camera app instantly appeared on your home screen.
Extending the SDA
My PDA had only one USB port where only power lines were connected. That was not expansive enough, so I took unused serial port on the MCU and braked it out on 1.27mm pin header together with ground and 3.3V. I used this small connector because of size constraints, It is not mechanically ideal for the job and only time will tell if it will survive harsh and dusty environment of my pocket.
With this contraption in place I added the software support for the serial port so it could be used from applications written in SVS. For the first hardware add-on I choose the U-blox NEO-6M GPS module that I had laying around and created:
Words most useless GPS
Hardware side of this add-on is quite simple: The GPS module is connected to the PDA with few wires. I quickly designed simple enclosure, printed and it works well enough. (I already designed better one, but didn't have the time to print it.)
Software was a bit more tricky because I found and fixed some bugs in SVS (design flaw in the string garbage collector took the most time and thinking). But ultimately after about 220 lines of SVS I was parsing the GGA NMEA command, showing the longitude and latitude and drawing cross marking your position on the 320px wide map of the world. It is accurate enough to guess the continent you are on.
What next
I have a DFPlayer Mini module laying around, so the next add-on will probably be MP3 player.
I am also finishing the schematics for next hw revision of my PDA. It will also have an extension connector and there will be some design features that will allow the extension to better hold on the PDA. That is actually the worst thing about the current design, the add-on can be unplugged too easily.
-
Sneaky update
03/31/2018 at 21:35 • 0 commentsSome time ago TCL announced that they will came up with Palm branded smartphone, so obviously I halted all work on my PDA and I am waiting on a android smartphone with a Palm sticker or something.
Just kidding...
What is new?
Software:
Lately I didn't have much free time to work on my PDA. But I was still using it and now with some time to spend on development, I fixed some bugs and started working on SDA_OS simulator for windows. I am also working on improvements in overall code quality and I will move it on GitHub as soon as possible.
Also I made a simple snake game for the SDA:
Hardware:
I have most of the parts for the new hardware revision. Now I am in the process of making parts symbols and footprints and incorporating them into existing schematics. I will design the PCB first, then I will move to the design of the case.
-
SVS - How not to make a programming language
02/22/2018 at 19:50 • 0 commentsI am still waiting for some parts that I will use in the next hardware revision of my SDA, so in the meantime, I will write a short introduction on how to not make programming languages. It is just a summary of pain-points that I encountered when developing the "amazing" SVS scripting language used in my PDA.
Step one:
Just start programming!
Don't bother with nonsense like specification, just open a textfile and start writing #include <stdio.h> int main() { printf(.... etc. etc. You can't be disappointed with the end product if you don't have any idea what the end product should be.
This was my approach and it didn't work well. I noticed it firstly when I was adding first new data type. Originally the script supported only unsigned int variables and constants. I wanted to add text strings and things went really badly because of many wrong decisions in the design stage. This was amplified by the fact that I was using C and I had to redesign many of the data structures I was working with. I made it work somehow, but it needed ugly workarounds here and there. For example: If you were working with a function that was returning string instead of:
a = function();
You needed to do:
a = "" + function();
Otherwise you got a type check error. I ended up rewriting all the expression solving logic in the end. Now SVS supports 32bit int type 32bit float and strings, although the conversions between those types are not perfect, it works way better than before.
Think a bit about the feature set in the early phase of development.
Step two:
You will never encounter invalid input and debugging is for losers
Your main goal when developing a programming language interpreter/compiler is to make it work with valid input data and when invalid data show up, just let it crash or something.
It turned out that when you are developing new application, your script interpreter will encounter more invalid inputs (somewhat broken programs) than the valid ones. Quality of error messages and error detection must be reasonably good. First versions of SVS just printed one of predefined error messages together with a number of the token where the error happened. Finding out what keyword in the source file corresponds with the right token was left on the user.
Now the debug output prints some parameters of the error and also prints a line in the source file where the error most probably occurred. This makes debugging much easier.Think about debugging from the start.
Step three:
Big, monolithic blobs of code are the best
Do not cobble things together, it doesn't work in the long time perspective. Splitting them up is just not fun. Try to split your code to logical layers and create understandable APIs.
Step four:
Documentation sucks!
Just do not bother yourself with documenting anything, the code will document itself. Or not? This is actually my biggest pain-point. With no documentation the project is useless to other people. Creating specification and documentation for a project is not fun, but it's actually really good in the long term. I recently finished documenting the main features of the SVS language. Documentation on how to use SVS in some C project will be published later.
And the best thing: SVS is now available on GitHub!
-
More buttons
02/14/2018 at 22:10 • 0 commentsAs part of designing a new prototype of my PDA, I was working on new case and buttons. Old buttons had some problems:
- There was too few of them (4 general purpose and one power button)
- They had weird feel to them
- Each one felt different
It turned out that button design is a bit harder thing to do than I previously thought. So I went back to the drawing board (FreeCAD). You can see updated buttons bellow.
If you are waiting for some great PCB design that will go underneath those buttons, then well... keep waiting. I am still waiting for some parts and I don't want to rush it. I mocked up the keypad part with some universal PCB.
After bit of artistic soldering and slight dissection of my PDA I ended up with updated keypad. After few button presses I found out that seller of the buttons must have mislabeled them, because they sure did not feel like they have operating force of 1 N. They felt better than the previous ones and that is what counts.
In conclusion, feel of the buttons has been improved, but choice of the switches was not great and buttons are a bit too hard to press.
I will post freecad and STL files for the new case when I will be done with it.
-
All about hardware
01/28/2018 at 20:28 • 0 commentsSome people on HaD asked me about schematics and PCBs because they want to build their own PDA. I don‘t really have a nice schematics and my current hardware has many shortcomings. Also much of the case is made out of hot glue and that’s not ideal.
Now I will mainly focus on new hardware revision (PCBs and case). My main goal is to design open-source hardware PDA. The current software stack will be replaced with something else in the future.
What will be improved or added:
- It will be possible to replicate easily
- SD card will be connected over SDIO instead of SPI
- Modular design will enable use of different LCD modules.
- PWM enabled LCD backlight
- I will replace MCU with something bigger (100 pin instead of 64 pin) to get more pins.
- 3.5 jack for possible mp3 playback
- Device will be powered from out of the shelf phone battery (some easy to get nokia or samsung one).
- There will be better buttons.
- Under-voltage protection and overall improved power circuitry.
- FTDI for better connectivity
Now I am looking for suitable displays and batteries (mainly their connectors). I will order the parts, draw schematics and make sure it works. Then I will release schematics and move to design of the
improved case. Two fellow hackaday users offered me to make the PCB layout so that‘s covered. There definitely will be few iterations of hardware design before it will be done.I will keep you updated on my progress.
-
More about the software
01/21/2018 at 22:03 • 4 commentsSDA_OS
SDA is in its current form just mess of wires in nice 3D printed case, it works, but its not a great piece of hardware. All its value is in the SDA_OS software stack. SDA_OS is cooperative single tasking operating system (if the only task doesn't cooperate, the system hangs) and it can run its own applications. Its most powerful feature is that there are two supported platforms: STM32 and Linux (Windows version is also possible). I did not aimed for this in the beginning, but being able to debug new applications and add new features easily on my laptop is really convenient.
SDA_OS has the same code base for both platforms, only the drivers are different. The linux part are just standard libraries and SDL for graphics and input. On the STM32 I use HAL libraries to handle peripherals (with some optimisations where the HAL is too slow) and FatFs library for handling the SD card.
For the Linux version I use simply GCC, for STM32 I got Eclipse with some CodeSourcery plugins. (I got it working once and never touched it since.)
Graphical library
I use simple graphical library of my own design. It is written in C and can be used on top of simple functions that can draw points or fill rectangles on a LCD. (basic lcd_set_xy, lcd_draw_point etc.) On the SDA the library draws on its display, in the simulator it is using SDL. Most of the basic functions for drawing lines and rectangles are borrowed from library that came with the lcd.
The text drawing function is custom and draws text in pre-rendered variable-width font, it supports Czech character set encoded as UTF-8. It don't support all of the UTF characters and it can crash on some special ones. The graphics library also have functions to determine size of the rendered text, it can draw cursor on specific position and it can automatically break too long lines of the text.
As only supported image format I selected the binary PPM. Gimp can export to it and it is dead simple to read and draw. Also I don't like BMP.Most basic block of my UI is a screen element, on screen you can add another elements (and also another screens), you can set the position of elements inside screen in a grid (you can set size of this grid) and also offset of all elements in the screen (useful for scrolling).
Supported UI elements are:
- Button
- Text (editable/non editable)
- Progress bar (horizontal, vertical)
- Scrollbar (horizontal, vertical)
- Icon
- Color button
- Check box
From those elements you can build a screen, and then draw it to lcd. The library can also receive user input for the screen, process it and set event in some element (if you click on button, the button will have EV_PRESSED in its event field). In the code to update the UI you can read and handle those events.
The library is written in a way that allows to redraw just the modified elements, so it's reasonably fast.
Downsides of this library are deep in its design, all elements sit in one big array and there are no barriers between applications, so they can rewrite each others elements. Also the array has fixed length, no dynamic memory allocation whatsoever, when you run out of elements, then you can't do much.
The scripting language
I wanted to be able to write applications for SDA on the SDA, in something like BASIC, but I was unable to find something like BASIC. I always wanted to learn how interpreters work and then I found this this awesome tutorial on how to write pascal interpreter in python. Python and C are somewhat different languages, but the concepts are the same and I started to design and implement my own simple blend of interpreted C, BASIC and maybe old GML (Game Maker Language). My goal was to do the high-level functionality in the script and the computation heavy things in a C framework.
I ended up with the SVS (SDA Virtuous Script maybe?). This is really the part of the software that took me the most time. After more than a year it supports functions, local and global variables, some operations with strings, statements like if-else, while, for and most importantly it is easy to connect it to C functions. It also can detect errors reasonably well and can print out the line of the code where the error most likely occurred. Enhanced command-line helloword looks something like this:
function main { a = "Result: "; hello(); sys print(a + add(1, 1)); } function hello { sys print("Hello World!"); } function add { return arg0 + arg1; }
This code outputs:
Hello World! Result: 2
And again, there is no dynamic memory allocation, so number of functions is fixed, number of variables is fixed and number of characters in the string memory is fixed.
What did I learn? I learn that writing parsers, interpreters and eventually compilers is really hard job and the things that we take for granted are the hardest to implement (like error checking, coping with wrong input...).
Making the applications
Applications are written in the SVS language and they are using frameworks that enables them to use the graphics library, the sound and all the other things (speaker, direct draw to LCD, reading text files, parsing ini and csv files, setting the system alarm).
Code for example application:function init { scr = sys pAddScreen(); sys pSetMainScr(scr); sys pAddText(0, 0, 8, 1,"Graphical Hello World!", scr); btn = sys pAddButton(1, 1, 5, 2, "button", scr); chck = sys pAddCheckBox(6, 1, 10, 2, "Checkbox", scr); sliderVal = 50; sld = sys pAddSliderH(1, 3, 9, 4, 100, sliderVal, scr); bar = sys pAddBar(1, 6, 9, 7, 100, sliderVal, scr); } function update { # comment if (sys pGetEvent(btn) == EV_RELEASED) { a = a + 1; sys pSetStr(btn, "" + a); } sys pSetEvent(btn, EV_NONE); if (sys pGetEvent(sld)) { sys pSetValue(bar, sys pGetValue(sld)); } sys pSetEvent(sld, EV_NONE); if (sys pGetEvent(chck) == EV_RELEASED) { sys pSetGrayout(btn, sys pGetValue(chck)); sys pSetGrayout(sld, sys pGetValue(chck)); sys pSetGrayout(bar, sys pGetValue(chck)); } sys pSetEvent(chck, EV_NONE); }
And here is what it does:
I am not showing the C side of things for purpose, it's really ugly and it's badly designed. Also I am the only one with the hardware (although there was version for the 32F769IDISCOVERY kit) and I don't think that anyone would be interested in running just the simulator, but if you want the sources, there is complete source tarball in the project files.
UPDATE: The SVS script interpreter is now available on GitHub.