fredag 30 juli 2010

ZRip - extract the Z code text adventure part of a zblorb file

The Z machine is a virtual machine used by Infocom in the 80's-90's so that they more easily could port their different text adventure games to the many different platforms of the time. The Z machine has its own instruction set called Z code. Some versions of the Z machine support images and sound.
IF-Archive contains many Z-code games playable on a Z machine.
The blorb-format is a format developed to collect the Z code, images and sound that were previously in separate files into one single file. (Btw, blorbs can contain code for other interpreters as well, not just Z code)
This is were ZRip comes in.
Blorbs can contain high resolution sound and images and become quite big and not suitable for machines with limited memory capacity. ZRip reads a blorb-file and tries to extract just the Z code.

Here's the source

onsdag 9 juni 2010

OpenOCD Ubuntu 8.10

sudo aptitude install libftdi1
sudo aptitude install libftdi-dev
./configure --enable-parport --with-ftd2xx-lib --enable-usbprog
make
sudo make install

onsdag 6 januari 2010

Computer controlled wall outlets

Got hold of three radio controlled wall outlets on sale. Modified the remote to be able to control the outlets with a pc parallel port (or some other port compatible with a 74xxx05)




The remote contains a sc2262 and is powered by a 12V battery.

After a look under the hood of the remote the conclusion was made that a press of a button connect two pins to ground, totally 5 pins are used giving six buttons (see schematic).
To control this from a computer a 74LS05 (hex inverter with open collector outputs) was used (any 7405 should do but if it's going to be powered by the parallel port it won't hurt using a low power one), connecting the open collector outputs directly to the control chip. The 7405 is powered using bit 5,6 and 7 of the data port, this is enough using the parallel port on my motherboard.


Schematic:




inside (the white wire is the antenna)



To control the parallel port this small (linux) program is used, ppdev module has to be loaded.


Remote.c
//Control of remote to remote controlled wall outlets using the parallel port
//Written for linux
//Written by Mikael Ågren 2009
//
//gcc remote.c -o remote

#include <stdlib.h>
#include <stdio.h>
#include <sys/io.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <linux/ppdev.h>
#include <fcntl.h>

int fd;

//map bits of pp data port
#define PWR    (1<<7)|(1<<6)|(1<<5)    //used to power buffer
#define ROD    1<<0
#define LILA    1<<1
#define GUL    1<<2
#define VIT    1<<3
#define SVART    1<<4

#define ON    ROD
#define OFF    LILA
#define ONE    GUL
#define TWO    VIT
#define THREE    SVART

unsigned char setParPortData(unsigned char data) {
    ioctl(fd, PPDATADIR, 0);
    if(ioctl(fd, PPWDATA, &data)) {
        printf("error writing to port");
        exit(2);
    }
}

delay_enough() {
    char i;
    for(i=0; i<5; i++) {
        delay_1s();
    }
}

delay_1s() {
    time_t t;
    time_t old_t;

    old_t = time(NULL);
    while ((t=time(NULL)) < old_t+1) {
    }
}

void printHelp(char **argv, int exitcode) {
    printf("usage: %s reciever on|off\nreciever = 1, 2 or 3\n", argv[0]);
    exit(exitcode);
}

int main(int argc, char **argv)
{
    if(argc!=3) {
        printHelp(argv, 1);
    }

    printf("Försöker öppna /dev/parport0\n");
    fd = open("/dev/parport0", O_RDONLY);
    if(ioctl(fd, PPCLAIM)) {
        perror ("PPCLAIM");
        close(fd);
        return 1;
    }
    printf("/dev/parport0 öppnad\n");

    unsigned char out=0;
    //which reciever
    if(!strcmp(argv[1], "1"))
        out |= ONE;
    else if(!strcmp(argv[1], "2"))
        out |= TWO;
    else if(!strcmp(argv[1], "3"))
        out |= THREE;
    else
        printHelp(argv, 1);
    //which state
    if(!strcmp(argv[2], "on"))
        out |= ON;
    else if(!strcmp(argv[2], "off"))
        out |= OFF;
    else
        printHelp(argv, 1);
    //keep buffer powered
    out |= PWR;

    printf("%x\n", PWR);    
    setParPortData(PWR);
    delay_enough();    
    printf("%x\n", out);    
    setParPortData(out);
    delay_enough();    
    printf("%x\n", 0);    
    setParPortData(0);

    close(fd);
    return 0;
}

Coffee...
Wrote some simple scripts so i can wake up to the smell and sound of fresh coffee in the morning

kaffeON
remote 3 on

kaffeOFF
remote 3 off

kaffe
if [ "$1" = "" ];
then
        echo "usage:    $0 now"
        echo "  $0 HH:MM"
        exit -1
fi

timeoff=$(date -d "$1 30 min" +%H:%M)
$(echo kaffeOFF | at $timeoff)

if [ "$1" = "now" ];
then
        void=$(kaffeON)
        echo $void
else
        timeon="$1"
        $(echo kaffeON | at $timeon)
fi

söndag 20 september 2009

DIY nop binary wristwatch

For some time i've wanted a binary wrist watch and a couple of days ago when I felt for doing a small project that could be realised fairly quickly i finally came to it.

Here's a list of some basic hardware "features" i strived for:
  • Fit inside a wrist watch
  • Use as few parts as possible
  • Surface mount components where possible
  • Only minute and hour representation is necessary
  • Driven by button cells for "long time" ie months without replacing
  • Leds to represent time
  • 24 hour format
  • As single sided pcb layout as possible since hand connecting vias is a drag

Now, why reinvent the wheel so I fired up my favourite search engine but I couldn't find anything to satisfy my needs. Most of the binary watches were based on the megax8 (which in my taste is way too big and has too many features for a project like this). Finally I chose a between a tiny24 and a tiny25 and the went with the tiny24, mainly because I would have to use all the pins of the tiny25 and therefore making programming of the device problematic. An advantage of using the tiny24 is that it's 16-bit counter's got power consumption characteristics in par with both the tiny25's and the megax8 8-bit counters. This results in that we don't have to wake the CPU as often and thus save power. The datasheets are very scarse on details regarding current consumption when a 32.768kHz crystal is used so this is just an assumption made by looking at frequency=0.1MHz in the Idle Supply Current vs. Low Frequency (0.1-1.0MHz) table. Current consumption values of the timers are found in table Additional Current Consumption (percentage) in Active and Idle mode.


The circuit 

The MCU is a Tiny24 (14 pin).
The leds are charlieplexed.
Q1 is a 32,768kHz crystal
The pushbutton is connected to INT0.

The software
To conserve power the microcontroller is put to sleep as soon as it doesn't do anything useful (TIMER1 has to be active so we use "idle mode").
The timekeeping part of the software is based on using TIMER1 to trigger an interrupt every minute which wakes the CPU and updates the time.
When the button is pressed an INT0 interrupt wakes the CPU and the time is displayed.
binwatch.c
binwatch.h
display2.S
Makefile

The PCB
It's a double sided pcb with microcontroller and leds on the top layer and battery and crystal on the bottom layer.
The battery holder is a low profile battery holder for cr2032 batteries.
The button is smd and placed on the right side of the following pictures.
The PCB is 3 cm in diameter.

 top
 

 bottom






The watch
The donor watch was an old broken lcd watch. I removed the button used to set time and replaced it with a small screw with conical head and it all fit quite nicely.
The leds looks much stronger "irl".




Thoughts
Time representation could be changed from 00:00-23:59 to 00:01-24:00, to avoid wondering about whether watch is broken or just displaying 00:00