-
A Fair Weather Friend
09/27/2024 at 03:46 • 0 commentsI work as a home repair contractor, and autumn becomes a very busy season for me as lots of people want to get things done before the rain begins. So I have not had any time to work on projects.
I did discover on a very overcast day, the device will only charge to about 2.9 volts, maybe more if in light all day... but the panel used in this project is rated 5v, 30mA, in full direct sun, it really only provides 15-25 mA.
On a very overcast day, current is only about 0.5 mA, and voltage much lower. Where I live we get about 6-8 months a year of such weather... It got me looking into energy harvesting IC's. But this project will not expand into that.
The device can be fully charged in about 10-20 min if placed directly under a bright lamp indoors.
I think all I will do on this project in the near future is assemble one of the PCB devices, and once all is tested release PCB files for that as well as update guide to reflect PCB assembly.
I am thinking of a more advanced handheld device to port TGRK to, using either STM32, or ATMEGA328P instead of attiny85. As this device will have either an LCD character display or OLED screen, it will use a LiPo battery for energy storage instead of a supercap. But will still retain solar charging capability, in addition to usb charging.
This new device will have a 16-20 key keypad for programming on the device. As character variables will be a new feature, as well as on screen programming, instead of modifying bytes bit by bit, we can type in keywords as they appear in the keyword table, and the interpreter will convert the text representation to the integer keyword code. Because of this the interpreter will have to be modified, but I do intend to make TGRK programs somehow compatable between devices.
-
PCB's and New Game Update
09/19/2024 at 18:06 • 0 commentsThe 5 PCB's I ordered came in. When I get the chance I will assemble one for testing.
I am thinking of making a video of assembling the PCB device, we'll see.
Somehow my "pet" survived through the night last night without making modifications to the game code. I was surprised and impressed! Making a day counter to see how many days it has survived is next on the plan for modifying the game code.
-
Virtual Pet Game
09/18/2024 at 19:27 • 0 commentsThe "Virtual Pet" game I wrote about in the last log seems to be working fine. Although I was not able to keep it alive overnight.
It seems like the voltage dropped below 2v during the night at some point, the power saving mode kicked in and the "pet" was not able to survive that.
Currently when pet wakes up from its 8 minute naps, one LED (showing overall health level) is lit for about 20 seconds, which is the overall timeout for getting user input. I need to set this so if after the first button timeout, there is no user input, LED is off. 20 seconds on every 8 min is roughly 2 min on every hour. During an 8 hour night thats 16 min of wasted power. During the winter where i live we get up to 16 hours of darkness. Ideally the pet can survive through the night.
Another idea is to have the pet "hibernate" if health (VCC voltage) drops below a certain level. Placing device in sun would be the only way to wake it in that case. While pet is in hibernation, no attention is needed from its owner. In this mode 16 hours has been tested for device not resetting and losing ram contents.
-
Multiple Interrupt Sources and Getting Button Input
09/17/2024 at 18:49 • 0 commentsI had an Idea to write a second game for the device, but in doing so I had to modify how the interpreter process button presses.
Up until this point, when the keyword to wait for a button press was called "BG", the interpreter would wait indefinitely until a button was pressed. But in this new game, if there is no user input, I want the device to go into deep sleep.
Also, because the buttons are on a resistor ladder, only the RUN button will wake the device up from deep sleep. I had to address the following issues and fix them:
- If no button is pressed when BG is called, after 5 seconds or set timeout, interpreter will continue. This allows the user to let the device go to sleep if there is no user input.
- When RUN button is pressed to wake interpreter from deep sleep (D0-D8), if it was not released fast enough, it would also kill the interpreter. As the RUN button is also the button used to exit the interpreter in normal operation. The fix was to set the "Button Pressed" flag to true immediately after waking, so the interpreter would not read another button press until the RUN button has been released and a new press is done.
- There was an issue with device not waking from button interrupt (PCINT3) or from WDT after one or two sleep cycles, it took me quite a while to fix the issue, and to this point I am not entirely sure what was causing the issues. It is confusing enough for me dealing with one interrupt source, but trying to deal with two simultaneously was conflicting. I think the issue was not disabling interrupts while clearing the PCINT3 flag. I will have to experiment with different types of interrupts more to understand them better. But now it is fixed. If we call (D8) in the interpreter, the device will go into low power mode for 8 minutes, or until the RUN button is pressed.
The second game I have written is a "Virtual Pet" game. The concept is fairly simple.
- When running program, if health is greater than 31 (25%), LED 1 will be lit, otherwise LED 0 will be lit. This allows the player to get a quick check on if there is immediate attention needed to the Pet.
- "Feeding" Pet is done by placing device in sunlight. We can think of the animals hunger directly proportional to the voltage level of the super capacitor. If that drops below 2 volts and device goes into low power mode, we sure as hell better hope some of it's other stats are high enough or when we recharge the device it will wake up dead!
- We can give the pet "water" by pressing the "<" button on device. Each press will add 10 points to it's water stat.
- We can "Pet" the creature by pressing the ">" button, which adds 10 to it's "attention" stat. Watering the pet also adds 1 to this stat.
- The pet's overall health and happiness can be viewed by pressing the "T" button, which will blink out a number between 1 and 127. This number is decided by the following formulas. Due to the order of operations TGRK calculates math, I had to write it in this format.
* R2 is pets "hunger", determined by (VCC - 27) x 5* * 0 = starving [(27 - 27) x 5 = 0] * * 127 = full [(53 - 27) x 5 = 130 (rounds to 127) * R2 PAXX SUB 27 MUL 5 * R7 and R8 Are temporary variables to store "Thirst" and "Attention" * * We divide all by 3, then add together to get a number between 0-127 * R7 R3 DIV 3 R8 R4 DIV 3 * R1 is pets overall health and happiness * * 0 = dead, 127 = Fat and Happy * R1 R2 DIV 3 ADD R7 ADD R8
I haven't been able to test the game thoroughly due to the button processing and waking from sleep issues I have since fixed. I will load it up on device today and see how long I can keep this thing alive.
With no input from user (Petting or Watering), every 40 or so minutes 8 thirst and 4 attention is subtracted from stats, every 8 minutes the device wakes up momentarily and increases a counter if no user attention is given. If the device is not in sunlight during this time, the hunger will increase as well.
I need to modify game code so pet can also die if it's not hungry, but hasn't had water for x amount of time.
It would also be cool to keep track of how many days the pet has been alive (roughly as far as the accuracy of attiny85's WDT), which would be easy to do. Every 15 sleep cycles would equal roughly 2 hours. Increment a counter when that happens, then increment another counter when that one gets to 12 (for ~24 hrs).
Full game code:
* A simple "Virtual Pet" game * * Charging via solar panel "feeds" pet, Pressing < button gives pet water, Pressing > button "pets" the pet. Overall pet health viewed by pressing T button. S button to exit game while pet is awake. R button to wake pet up from sleep. Pet will "Sleep" for 8 minutes at a time, each time a pet wakes up, it's thirst and "attention" stats decrease. These can be increased by pressing > and < buttons. Pet's "hunger" increases as super capacitor voltage decreases, the only way to "feed" the pet is by placing pet in sunlight or directly under a very bright lamp. * F1 FUNC BG CE BV 0 R6 ADD 1 R5 ADD 1 CGE R5 7 R3 SUB 8 R4 SUB 4 R5 0 SEP CE BV 1 R6 0 R3 ADD 10 R4 ADD 1 SEP CE BV 2 R6 0 R4 ADD 10 SEP R2 PAXX SUB 27 MUL 5 R7 R3 DIV 3 R8 R4 DIV 3 R1 R2 DIV 3 ADD R7 ADD R8 CE BV 3 R6 0 BB R1 FUNC F2 FUNC CGE R1 31 L1H L0L SEP CL R1 31 L1L L0H FUNC F3 FUNC F2 F1 CGE R6 5 D8 R6 0 R5 ADD 1 S1 SEP CG R1 0 AND CNE BV 4 LPF FUNC F3 EOP
-
More Game Balance Changes
09/11/2024 at 23:33 • 0 commentsI changed some things with the games balance.
Firstly player starts with max HP (127), instead of 64.
I also slightly amount monster does damage.
There was a bug in the gold drop. If you look at the code you will probably spot it. Basically it was adding our variables to player gold, then dividing. I fixed this by setting another registers variable to the formula result, then adding that to player gold register.
With these new changes I have been able to get to level 108! Which is just 8 levels away from the end.
I Think at this point it is beatable but from about level 105-126 the player pretty much has to travel back to the inn after each fight to heal. Which becomes very tedious. Before these changes to game code after about level 55 player had to go back to heal after each fight. But that may have been mainly to the gold drops not being calculated correctly.
I would like to add a fast travel to and from inn. Where each map being traveled will blink quickly so there would still be a sense of travel time but not having to click a button 100 times each way. To do this I need to shave off some bytes somewhere. I am not sure if its possible but will look it over again and see.
There was also a bug in how the serial transfer tool was parsing comments, which I fixed. If the comments beginning and ending asterisk didn't have a space before and after it, strange things would happen. Now as long as the outside of comment asterisk is not touching a program keyword or value, it works as it should.
-
Game Difficulty
09/11/2024 at 01:12 • 0 commentsA turn based game that only has 2 input buttons is fairly easy, unless it is programmed in a way that it is unbeatable.
The only skill required in this game is reading the binary number for HP, and deciding if its time to go back and heal.
So far the highest level I have reached is level 85. At that point after each fight the player has to return to the inn to heal. If a monster only drops 10-20 gold, thats not enough health to survive another fight, much less two.
The game is definitely playable at this point, but I am unsure if it's beatable. I need to really look at my game code and see if i can shave off a couple bytes somewhere and add some more complexity to the Player/Monster hit formulas, as well as the gold drop formulas.
I suppose I could also give player 2 HP per gold spent, and each night at the inn costs player 64 gold.
Anyhow, I am happy with where the project is for the end of contest, but I will be improving it when I get the time.
-
Gameplay Video
09/10/2024 at 13:04 • 0 commentsGameplay video
-
Updates and Video
09/09/2024 at 05:44 • 0 commentsI had to really really slim the game code down, as well as change a few features in the interpreter code to accommodate some things for the game.
Here is a somewhat long video demonstrating the game code and serial transfer program. I will try and make a video of playing through the game tomorrow.
Here are the new changes, mainly the previously mentioned way of handling button input in the interpreter. There are always small changes I do but forget about to mention on here, but any changes to do with using keywords will be updated on the Keyword Table file.
Using the keyword
BG
waits until a button press. When a button is pressed, it is stored in the "BV", and can be accessed like any other register:
* Wait for button press * BG * Set value of R1 to button value (1-4) * R1 BV * Check if we pressed button 2 * CE BV 2
Another thing I changed was accessing single byte EEPROM addresses. Before only 3 bytes at end of EEPROM were accessible using 6 different keywords, 3 for writing, and 3 for reading. I did this to reduce byte size in programs. But it felt too limited, so now there are only 2 keywords for accessing an EEPROM byte, and byes 382-502 are accessible to user to save data in, like this:
* Write to EEPROM * EW (address) (value) EW 0 R1 EW 1 12 * Read from EEPROM * Rx ER (address) BB ER (address) R1 ER 0 BB ER 117
It now takes 3 bytes in program code to save to EEPROM, and 3 bytes to read.
The address can be 0-117. 8 bytes at end of EEPROM are saved for a feature to be later implemented.
This future feature will have one keyword for saving all 8 registers to last 8 bytes in EEPROM, and one keyword for loading those bytes back into the 8 registers. This could be good for saving a game, etc.The EEPROM keyword and address can not be used in a conditional like this:
CG ER 32 12 CE R3 ER 0
This will result in an error. This is not a bug but a feature... For now.
Now on to the new game code. I was able to pack a "fully" functional "RPG" game in 127 bytes. Think Pokémon on a one dimensional linear map with only 2 LED's to know what is going on in the game. This was quite the challenge, but I am glad I was able to program it in TGRK instead of adding it into the Arduino sketch.
It ended up having a lot less features then originally planned, but I think with the right tweaks the difficulty can make it enjoyable to play. That is if you don't mind reading the binary codes blinked out to monitor your health level, and subtracting or adding to those blinks to know how many hit points you lost in the last battle, or how much gold you just spent on healing at the inn.
Game Code
R2 64 F1 FUNC CE R8 0 BG L0L L1L CE BV 2 L1H R1 ADD 1 CG R1 R7 CG RND 64 R5 R1 DIV 2 ADD 1 R8 1 SEP CE BV 1 L0H R1 SUB 1 R8 0 CE R1 0 R2 ADD R3 R3 0 BB R2 SEP CE R8 1 L1H L0H R6 RND ADD R1 ADD R5 DIV 12 R2 SUB R6 R8 2 SEP CE R8 2 R6 R2 ADD R3 ADD RND DIV 12 ADD 1 R5 SUB R6 R8 1 S1 CLE R5 0 R7 R1 R3 ADD RND ADD R1 DIV 2 ADD 1 R8 0 BB R2 L1L L0L SEP CG R2 0 CLE R1 126 LPF SEP CE R1 127 BB -1 LP FUNC F1 EOP
I am not going to explain this code in any detail in this post, I go over it line by line in the video. But the key to getting it all in so it was functional was taking out all the AND keywords where you see nested conditional statements. This saved me 5 bytes which was all I needed to add the led control keywords in the right spot to know what the hell is going on while trying to play this abomination.
-
Game code
09/07/2024 at 06:05 • 0 commentsHere is the complete game code in TGRK. It ended up being 294 bytes, so I cannot test it on the device. My options for running this game are either A. expand the program size from 127 to 300 bytes, which would make me have to refactor a lot of different things. or B, implement the game in C and have it as a feature on the device.
Probably going to keep the interpreter as it is and add the game as an extra feature. Either way, it was fun writing this program in TGRK:
EDIT: I Slimmed it way down. Removed the menu system and just have < > and T buttons. The math for damage and monster health calculations had to be slightly slimmed down as well. As well as removing the option to roll to run away. Now during a fight you can just run.
I also removed XP, and changed gold (Stored in R3) as the players damage multiplier. HP is also a damage multiplier.
Simplified Code now fits in exactly 127 Bytes. Will get my serial dongle out tomorrow and drop it on there and see if it works!
* FIGHT * F7 FUNC CG RND 64 AND CE R8 3 AND CG R1 R7 R5 R1 DIV 2 R8 1 SEP CE R8 1 R6 RND ADD R1 ADD R5 DIV 12 R2 SUB R6 R8 0 SEP CE R8 2 R6 R2 ADD R3 ADD RND DIV 12 R5 SUB R6 R8 1 SEP CLE R5 0 R7 R1 R3 ADD RND DIV 2 R8 0 FUNC * CONTROLS * F8 FUNC BG L0L L1L S1 CE BV 1 R1 SUB 1 L0H SEP CE BV 2 R1 ADD 1 R8 3 L1H SEP CE BV 3 L1H L0H R8 2 SEP CE BV 3 AND CE R1 0 R2 ADD R3 R3 0 BB R3 SEP F7 FUNC R2 64 * MAIN LOOP * CG R2 0 AND CLE R1 126 F8 LP EOP
Original Code:
R2 64 * INN * F1 FUNC CE R8 0 AND CG R2 0 R2 ADD R3 R3 0 SEP CE R8 1 BB R3 SEP CE R8 2 BB R2 SEP CE R8 3 R1 ADD 1 SEP FUNC * MONSTER ATTACK * F2 FUNC R6 RND ADD R1 ADD R5 DIV 12 R2 SUB R6 FUNC * PLAYER ATTACK * F3 FUNC R6 R2 ADD R4 ADD RND DIV 12 ADD 1 R5 SUB R6 CLE R5 0 R7 R1 R4 ADD R1 DIV 10 R3 ADD RND ADD R1 DIV 2 ADD 1 FUNC * FIGHT MENU * F4 FUNC CE R8 3 F2 SEP R8 3 BG CE BV 1 AND CG RND 60 R1 SUB 1 R5 0 R8 0 SEP CE BV 2 AND CG RND 50 R1 ADD 1 R5 0 R8 3 SEP CE BV 3 F3 SEP CE BV 4 BB R2 R8 2 SEP CG R5 0 AND CG R2 0 LPF SEP R8 3 FUNC * ROAD MENU * F5 FUNC CE R8 3 R1 ADD 1 SEP CE R8 0 R1 SUB 1 SEP CE R8 1 BB R1 SEP CE R8 2 BB R2 SEP CG RND 50 AND CG R1 R7 R5 R1 DIV 2 ADD 1 F4 FUNC * MENU LED * F6 FUNC CE R8 0 L0L L1L SEP CE R8 1 L0H L1L SEP CE R8 2 L0L L1H SEP CE R8 3 L0H L0H FUNC * BUTTON INPUT * F7 FUNC BG CE BV 1 AND CG F8 0 F8 SUB 1 F6 SEP CE BV 2 AND CL F8 3 F8 ADD 1 F6 SEP CE BV 3 AND CE F1 0 F6 F1 SEP CE BV 3 AND CG F1 0 F6 F5 FUNC * GAME LOOP * F8 FUNC CG R2 0 AND CLE R1 126 F7 LP SEP CE R1 127 L1L L0H S1 L0L L1H S1 LP SEP L1H L0H S1 L1L L0L S1 LP FUNC EOP
-
RNG
09/06/2024 at 16:21 • 0 commentsTo generate psuedo random numbers for use it the game, I found a method that seems like it will work great for the randomness I need.
Every time a button is pressed, we get the LSB of current millis() timestamp.
Our variable "int8_t random_number" is our global variable for storing the current random number.
First we shift bits 1 position left.
Then XOR the LSB
Then apply the variable to bitmask 127, which will guarantee the MSB is never a 1. We don't want any negative numbers stored in this variable.
Considering a button will be pressed every time any action is done in game, the generator will generate a new number every time a button is pressed, then we can read that number for applying to our game code.