Sunday, September 11, 2016

Super Simple Interpreter

I was wondering how to write a simple interpreter in assembly for a 6510 processor (#c64) and I dawned upon probably the simplest interpreter ever (aside from a brainfuck interpreter).

Here is the basic pseudo code of the program:
define array of lines
define dictionary of variables
define left variable
define right variable
define counter and set to 1

loop
    write '> '
    get line
    append line to array of lines if line not empty
    break loop if line is 'run'
end loop

loop for each line
    split line by spaces

    if first element is 'print' or 'write' then
        if second element is single quote do
            get second to last element
            join with spaces
            write string excluding first and last character
        end
        else do
            find second element from dictionary of variables
            get value associated with element
            turn value to string
            write value string
        end
        if first element is 'print' do
            write '\n'
        end
    end

    else if second element is '=' do
        if third element is number do
            set left to number
        end
        else do
            get variable name
            find value from variable dictionary
            set left to value
        end
        if line is > 3 elements do
            if fifth element is number do
                set right to number
            end
            else do
                get variable name
                find value from variable dictionary
                set right to value
            end
            if fourth element is '+' do
                left = left + right
            end
            if fourth element is '-' do
                left = left - right
            end
            if fourth element is '*' do
                left = left * right
            end
            if fourth element is '/' do
                left = left / right
            end
        end
        set dictionary position of first element to value of left
    end

    else do
        write 'Error on line ' + counter
        break loop
    end

    counter = counter + 1
end loop

The syntax of this interpreted language is this:
Each operation is its own line.
The mathematical operations are limited to +, -, *, /
All numbers are integers and operations return integers.
Strings are only allowed in print/write statements.
Strings are enveloped in single quotes.
Variable names must be single letters.
All individual parts of a line must be separated by 1 space.
Write writes to screen without newline.
Print is like write but with a newline.
No direct string concatenation, use write statements for that.

Example program:
a = 5
write 'A is: '
print a
b = a + 5
b = b / 7
write 'B is: '
print b

Example output:
A is: 5
B is: 1

To test its simple nature, I wrote the original version of the interpreter in Python 2.7 and was able to make it in 26 lines of code. Here is the source:
import sys
varis = {}
lines = []
write = sys.stdout.write
while 1: #get input
    inp = raw_input("> ")
    if inp == "run": break
    lines.append(inp)
for y in range(len(lines)): #parse program
    x = lines[y].split()
    if x[0] == "print" or x[0] == "write":
        if x[1][0] == "'": write(" ".join(x[1:])[1:-1])
        else: write(str(varis[x[1]]))
        if x[0] == "print": write("\n")
    elif len(x) > 2 and x[1] == "=":
        if ord(x[2][0]) > 96 and ord(x[2][0]) < 123: left = varis[x[2]]
        else: left = int(x[2])
        if len(x) > 3:
            if ord(x[4][0]) > 96 and ord(x[4][0]) < 123: right = varis[x[4]]
            else: right = int(x[4])
            if x[3] == "+": left += right
            elif x[3] == "-": left -= right
            elif x[3] == "*": left *= right
            elif x[3] == "/": left /= right
        varis[x[0]] = left
    else: print "Error: line "+str(y+1)

I then wrote a modified version of it in Axon (the main programming language I use at work) and I was able to make it in 31 lines of code. Here is the source:
(x) => do
  vars: {}
  x = x.replace("\n",";").split(";")
  t: []
  cou: 1
  left: ""
  right: ""
  x.each y=> do
    t = y.split(" ")
    if(t[0] == "print") do
      if(t[1][0..0] == "'") echo(t[1..-1].concat(" ")[1..-2])
      else echo(vars.trap(t[1]))
    end
    else if(t[1] == "=") do
      if(t[2][0] > 47 and t[2][0] < 58) left = parseInt(t[2])
      else left = vars.trap(t[2])
      if(t.size > 3) do
        if(t[4][0] > 47 and t[4][0] < 58) right = parseInt(t[4])
        else right = vars.trap(t[4])
        if(t[3] == "+") left = left + right
        else if(t[3] == "-") left = left - right
        else if(t[3] == "*") left = left * right
        else if(t[3] == "/") left = floor(left / right)
      end
      vars = vars.set(t[0], left)
    end
    else echo("Error: line "+cou)
    cou = cou + 1
  end
end

The differences in each of the implementations is that the Python one is more like a command line in which you type in your lines and then type in "run" when you want to execute the program, and it supports both "write" and "print". The Axon implementation only has "print" and is a function that takes in the whole program as a string parameter, so I made that to also work with semicolons between the statements.

Friday, April 8, 2016

Easily Install Oracle's Java On Ubuntu Linux

Hello world, today I have a quick "life hack" type thing for Ubuntu people.

Where I work, I am kind of the Linux guy, installing our software for clients who wish to run it on Ubuntu machines.
The problem is that our software runs on Java, and some of the people either don't know how to install Java or have it installed in a weird way.

I was asked what was the easiest way to install Java, and here you go:

sudo add-apt-repository ppa:webupd8team/java
sudo apt-get update
sudo apt-get install oracle-java8-installer
(agree to the two prompts)
(wait for download to finish)
java -version


The first 2 commands installs the webupd8team Java repository and updates apt-get so you can install from there.
The next command actually installs it, with a license agreement and a download.
The last command just confirms that you have Java installed.

Sunday, March 20, 2016

Making C64 Program Tap Files

Before I go ahead and tell you guys how to make a tap file that is loadable in a C64 emulator, I'm going to give you the link to the source of all my info: http://c64tapes.org/dokuwiki/doku.php?id=loaders:rom_loader and http://c64tapes.org/dokuwiki/doku.php?id=analyzing_loaders

This is where I learned how to make tap files (although it took me two weeks to find that page).

Enough chat, here is the structure of a C64 tap file.
There are 3 different kinds of pulses:
-    a long pulse lasting about 672 µS represented as ASCII char 86 or hex 56
-    a medium pulse lasting about 512 µS represented as ASCII char 66 or hex 42
-    a short pulse lasting about 352 µS represented as ASCII char 48 or hex 30
Physically, these pulses are square wave pulses running at 50% duty with a period of the specified µS.
I will refer to long as L, medium as M, and small as S. Data encoded using a combination of these pulses will be referred to as LMS format.

Now these pulses alone don't make up binary data (as I learned the hard way).
Bits are represented as a pair of pulses, a 0 bit being SM, a 1 bit being MS, a start bit being LM, and a data end bit being a LS.
A LMS byte is represented as a certain sequence of pulses which looks like this:
LM     xx    xx    xx    xx    xx    xx    xx    xx    nn
start  bit0  bit1  bit2  bit3  bit4  bit5  bit6  bit7  check

There is a start bit in front of every byte, but each byte doesn't have its own end bit. The check bit at the end is calculated with the bitwise formula:
1 xor bit0 xor bit1 xor bit2 xor bit3 xor bit4 xor bit5 xor bit6 xor bit7
Or more conveniently, if the byte has an even number of 1's, the check bit is 1, if the byte has an odd number of 1's, the check bit is 0.

Now that single bytes are covered, it's time to learn how whole data is encoded in a tap file.

Every C64 tap file starts off with 20 bytes of information, kind of like meta data. All information should be coded in hex, as this is raw data.
Bytes 0 to 11 are C64-TAPE-RAW, byte 12 is the number 1, bytes 13 to 15 are just 0, and bytes 16 to 19 is the length of the actual tap data in least significant byte first (LSBF) format. The tap data length is usually added last, since we don't know how long our tap data is yet.

The rest of the bytes are the data.
We start with 27136 small (S) pulses, this is the leader block used to calibrate the datasette speed.
Then we start the header with 9 sync bytes, from 137 down to 129 (LMS).
Then we write the header file type, in this case just the number 1 (LMS).
Next is the starting address for the data, two bytes in LSBF format (LMS).
Next is the ending address for the data plus 1, also two bytes in LSBF format (LMS).
Then the bytes in PETSCII code for the file name, no more than 16 bytes (LMS).
Then 16-lengthOfFileName bytes of the number 32 for title padding (LMS).
Then write the number 32 for 171 times, this is the header body, not sure what it's for (LMS).
Then a checksum byte for the header, this is all the bytes from the header file type (byte1) to the end of the header body (last byte) (LMS), use this bitwise formula to calculate:
0 xor byte1 xor byte2 xor ... xor last byte
Then a data end bit of LS to end the header.
Then we write a small pulse 79 times as an interblock gap.

Now we write the header again, but with some changes.
Write the 9 sync bytes, but this time from 9 to 1 (LMS).
Then write the exact same header data from the header file type to the data end bit (LMS).
Next write 78 small pulses as the header end trailer.
Then write 5376 small pulses as the interrecord gap.

Now we can start writing our actual program data.
Before we do that, you'll need to know how to make program data (useful link: https://www.c64-wiki.com/index.php/BASIC_token) or get it from RAM. (Or use my tapwriter.py program on GitHub)
Start the program with 9 sync bytes, from 137 down to 129 (LMS).
Next write the bytes of your program exactly how it would appear in ram from the starting address to the ending address (LMS).
Then write your checksum byte, calculated just like on the header blocks, only from after the sync bytes all the way to before this checksum byte (LMS).
Then write your data end bit of LS to end the header.
Then write a small pulse 79 times as the interblock gap.

Now we write the program data again, just like with the header.
Write the 9 sync bytes, but from 9 to 1 (LMS).
Copy the program block from after the sync bytes all the way to the data end bit.
Then write a small pulse 78 times for the data end trailer.

That's all there is to it, just remember to update the tap data length in bytes 16 to 19, this is only the length from byte 20 to the end.

This isn't the most efficient way to store data, since it takes about 10 seconds just to get to the header after the leader block, but it works and it's pretty cool to have a program load off a tap file that you made (forged with your own hands in the heart of a dying star).

If you understand how to create a tap file, and can actually get it to work (took me 3 days), then it wouldn't be hard to reverse the protocol to read the data off of the cassette or even directly from the C64, just as I will be doing for my C64 Arduino Internet project.

GitHub program files:
https://github.com/koppanyh/C64Net/blob/master/tapwriter.py

Wednesday, October 21, 2015

Pebble Time Watch - Shutting Down a Server

Here's my story: I have this server computer that I turn on every morning. It runs some basic server stuff, syncs my FitBit to the internet and charges my phone. I turn it off before I leave to school or work in the morning because it cannot be accessed from outside my LAN network and would otherwise waste energy with no one there to use it.

Here's my problem: To turn it off, I normally have to SSH into the server and run the command "sudo poweroff". This normally takes longer than I would like, especially if I happen to be running late.

Here's my solution: Make an app for my Pebble Time smart watch that could turn my server off easily.

My Implementation: I decided the best way to do this was to take advantage of the PHP part of the web server, running Apache 2 on an Ubuntu Server 14.04 box. I could make a web page that runs the Linux shutdown command and replies something through HTML. Then I could make an app for the Pebble Time smart watch that calls the page and displays the status.
The PHP code looks like this:
Poweroff ---
<?php
  echo(exec("sudo poweroff"));
?>

It is just a small PHP script called poweroff.php that runs the poweroff command and returns "Poweroff ---" plus whatever might be appended from the poweroff command. Running it is as simple as just calling "http://IPofServer/poweroff.php".
It's important that the Apache 2 web server is given admin permissions, otherwise it cannot run the "sudo poweroff" command. To give it admin permissions, run this command in terminal: sudo visudo and write this line to the end of the file: www-data ALL=NOPASSWD: ALL then press Ctrl+x, press y, press enter and you should be good. Type sudo service apache2 restart to restart the Apache 2 server and apply the changes, or just reboot the whole server.
The watch app itself was written using the Pebble.js method, this way I didn't have to waste a lot of time making it in C, but I might port it later. The code is very simple:
var UI = require("ui");
var ajax = require("ajax");


var card = new UI.Card({ //init the card
  title: "Shutdown",
  subtitle: "USERV2",
  body: "LOADING..."
});
 
card.show(); //show the card
 
ajax( //send the shutdown request
  {url: "http://IPofServer/poweroff.php"},
  function(data){ //success function
    card.body("STATUS: "+data);
  },
  function(error){ //error function
    card.body("ERROR - Cannot Reach Server: "+error);
  }
);


How it works: The app just initializes a card screen and all the parameters are hard coded, but I'm planning on changing that in a possible future update. The app then sends an AJAX request to my server (where it says IPofServer, change to an actual IP) and calls the shutdown page. The shutdown page return some text, in my case "Poweroff ---", and proceeds to send the shutdown command to the system. The watch receives the output of the server and replaces the "LOADING..." (on the image) with "STATUS: Poweroff ---". If it cannot reach the server or something goes wrong, then the watch says "LOADING..." for a while and then returns "ERROR - Cannot Reach Server: " with any errors appended to it. Once you see "Poweroff ---" then you know the server is shutting down and you can press the back button on your Pebble and proceed with whatever you were doing previously.

Screenshot of emulator with shutdown app.

Friday, October 16, 2015

Sale on GearBest.com!!!

Hey guys, there's a sale happening on GearBest.com right now: http://www.gearbest.com/promotion-electrical-amp-tools-special-233.html

In case you happen to miss it, just remember that GearBest.com always has cool stuff at rock bottom prices! And keep an eye out for any possible sales, they are somewhat frequent.

Thursday, August 20, 2015

Simple Python Command Line Calculator

Hello world, today I have something that is actually useful :p

So I commonly do a lot of small math, but I also prefer to use the command line to do everything... not sure why though. I later found out that there was a similar utility called bc, but it doesn't seem as functional as I would need it to be.

Anyway, I wrote a tiny Python script that is capable of doing everything I need it to... and more. Essentially it's a Python command line interface that is geared towards math. You type in a mathematical function, and it spits out the answer. It also saves the answer to a variable called "a" for answer. You can use that variable in your math normally in case you need the previous answer for your next calculation. You can also define your own variables just like "b = 5+3" or something, and still use them for calculations.

One of the biggest features, is the ability to use the Python interface instead of just doing math. Say you want to exit, all you have to do is type in "exit()" just as you would to exit a normal Python shell. Anything that works in a normal Python shell should work in this one also. But it's geared more for speed of calculations than running Python functions.

*Note* It is recommended you have experience with Python to use this as the math functions might not be so intuitive for someone who's never used Python before. Everything is calculated as an integer unless it becomes a float (by adding ".0" at the end of a number); 25/4 comes out as 6, but 25.0/4 comes out as 6.25. You can use the traditional math functions like cos() and sin() and sqrt() and all those functions that are found in the Python math library.

I didn't attach code because those 7 lines in the picture below are all that's needed and it shouldn't take more than a minute to copy it. The terminal shows how things look/work.


Monday, August 3, 2015

Present from China!

Hello world, today a package from The People's Republic of China came in the mail for me.


A few weeks ago, a representative from GearBest.com reached out to me regarding a generous offer. I was told that I could receive free items in exchange for documenting a project and giving a review. I accepted, chose my products and waited for the package to arrive. It finally came, I was pretty happy.

Inside was an Arduino Nano clone, a DHT22 temperature/humidity sensor, a 16x2 LCD module, a 433 MHz transmitter and receiver, and an MB102 breadboard power supply. In total, it cost $21.08, an extremely generous amount for such a simple task.

I'm planning on making a clock type thing that also displays temperature and humidity. Afterwards I might make an autonomous robot with the Clocky robot!

These things will be documented on Instructables.com