Category Archives: IceCrew

Little Led Matrix Maze game

While doing stuff like, making our home a little greener. Smoking meat. Working on diorama’s and my Escape game. I found time to make this little maze game.

Using an ESP32, mini joystick and a 8×8 led matrix. The objective is to get to the other side of the invisible maze.

It is a blind maze, so you have to figure out the path by trail and error. I found it quite fun and entertaining. (Coline had a hard time finishing the mode 3 maze)

I’ve got 3 settings on the maze:
0 – There is a trail where you have been.
1 – No trail, but only red leds showing walls.
2 – No trail, red reds and a reset to square 0,0 .. so you have to remember the path you previously took.

I’ll add code and schematics tomorrow …

Light blue shows you where you have been

Mode 2 game, reset when hitting a wall

Hitting the end block!

Maze is static at the moment, i’m planning to implement a “Recursive division method” to generate the maze.

Code

#include <Arduino.h>
#include <Adafruit_NeoPixel.h>

// joystick pins
int up=33;
int down=25;
int left=32;
int right=26;
int cursor=32;

// 0 easy = trail // 1 only red walls // 2 = reset to 0.0
int mode=2;

//int trail=32;
int trail=0;

// Which pin on the Arduino is connected to the NeoPixels?
#define LED_PIN    2

// How many NeoPixels are attached to the Arduino?
#define LED_COUNT 64

// Declare our NeoPixel strip object:
Adafruit_NeoPixel strip(LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800);

// bits set opening in square
//    2
//   -----
// 1 |   | 4
//   -----
//     0
// so 5 is a passage from left to right (1+4) 

int maze[8][8] = {
  4,5,3,6,5,5,5,3,
  6,5,11,12,5,3,6,9,
  14,1,12,5,3,10,12,1,
  12,5,5,3,10,12,5,3,
  2,6,5,9,14,5,1,10,
  10,10,6,5,9,6,5,9,
  12,11,10,6,1,10,6,1,
  4,9,12,13,5,13,13,1,
  };

int displaymatrix[8][8] = { 
{ 0,1,2,3,4,5,6,7 },
{ 15,14,13,12,11,10,9,8 }, 
{16,17,18,19,20,21,22,23},
{31,30,29,28,27,26,25,24},
{32,33,34,35,36,37,38,39},
{47,46,45,44,43,42,41,40},
{48,49,50,51,52,53,54,55},
{63,62,61,60,59,58,57,56}
};

int x = 0;
int y = 0;

void setup() {
// joy
  pinMode(32, INPUT_PULLUP);
  pinMode(33, INPUT_PULLUP);
  pinMode(25, INPUT_PULLUP);
  pinMode(26, INPUT_PULLUP);

// mode set with jumpers
  pinMode(34, INPUT_PULLUP);
  pinMode(35, INPUT_PULLUP);

  Serial.begin(115200);

  strip.begin();
  strip.show(); // Initialize all pixels to 'off'
  strip.setBrightness(10);
// set begin and end pixel
  strip.setPixelColor(displaymatrix[x][y], 0, 0, 255);
  strip.setPixelColor(displaymatrix[7][7], 0, 255, 0);

  strip.show();
//mode select  
 if (digitalRead(34) == 0) {
 mode=0;
 if (digitalRead(35) == 0) {
 mode=2;
 } else { 
 mode=1; 
 }
// finish effect
uint32_t Wheel(byte WheelPos) {
  WheelPos = 255 - WheelPos;
  if(WheelPos < 85) {
    return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3);
  }
  if(WheelPos < 170) {
    WheelPos -= 85;
    return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3);
  }
  WheelPos -= 170;
  return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
}

// reset to start (mode 2)
void reset2start() {
      strip.setPixelColor(displaymatrix[x][y], 0, 0, 0);
    strip.show();
  x = 0;
  y = 0;
  strip.begin();
  strip.show(); // Initialize all pixels to 'off'
  strip.setBrightness(10);
  strip.setPixelColor(displaymatrix[x][y], 0, 0, 255);
  strip.setPixelColor(displaymatrix[7][7], 0, 255, 0);
  strip.show();

}
// finish effect
void rainbow(uint8_t wait) {
  uint16_t i, j;
  for(j=0; j<256; j++) {
    for(i=0; i<strip.numPixels(); i++) {
      strip.setPixelColor(i, Wheel((i+j) & 255));
    }
    strip.show();
    delay(wait);
  }
}

void loop() {
    int isUp = (bitRead(maze[x][y], 1));
    int isRight = (bitRead(maze[x][y], 2));
    int isDown = (bitRead(maze[x][y], 3));
    int isLeft = (bitRead(maze[x][y], 0));
if (digitalRead(up) == 0) {
  if (isUp == 1){
  strip.setPixelColor(displaymatrix[x][y], 0, 0, trail);
  x++;
  if ( x > 7) { x=7;}
  strip.setPixelColor(displaymatrix[x][y], 0, 0, 255);
  strip.show();
  } else {
    strip.setPixelColor(displaymatrix[x][y], 255, 0, 0);
    strip.show();

    if (mode == 2){ 
      delay(1000);
      reset2start();
    }
  }
}
if (digitalRead(down) == 0) {
  if (isDown == 1){
  strip.setPixelColor(displaymatrix[x][y], 0, 0, trail);
  x--;
  if ( x < 0) { x=0;}
  strip.setPixelColor(displaymatrix[x][y], 0, 0, 255);
  strip.show();
  } else {
    strip.setPixelColor(displaymatrix[x][y], 255, 0, 0);
    strip.show();

    if (mode == 2){ 
      delay(1000);
      reset2start();
    }
  }
}
if (digitalRead(left) == 0) {
  if (isLeft == 1){
  strip.setPixelColor(displaymatrix[x][y], 0, 0, trail);
  y--;
  if ( y < 0) { y=0;}
  strip.setPixelColor(displaymatrix[x][y], 0, 0, 255);
  strip.show();
  } else {
    strip.setPixelColor(displaymatrix[x][y], 255, 0, 0);
    strip.show();
    if (mode == 2){ 
      delay(1000);
      reset2start();
    }
  }
}
if (digitalRead(right) == 0) {
  if (isRight == 1){
  strip.setPixelColor(displaymatrix[x][y], 0, 0, trail);
  y++;
  if ( y > 7) { y=7;}
  strip.setPixelColor(displaymatrix[x][y], 0, 0, 255);
  strip.show();
  } else {
    strip.setPixelColor(displaymatrix[x][y], 255, 0, 0);
    strip.show();

    if (mode == 2){ 
      delay(1000);
      reset2start();
    }
  }
}
if (x ==7 && y == 7){
  strip.begin();
  strip.show(); // Initialize all pixels to 'off'
  rainbow(20);
}
delay(200);

}

MCH 2022

Back from the hackers event “May Contain Hackers”

MCH2022 is a nonprofit outdoor hacker camp taking place in Zeewolde, the Netherlands, July 22 to 26 2022. The event is organized for and by volunteers from the worldwide hacker community.

Knowledge sharing, technological advancement, experimentation, connecting with your hacker peers and hacking are some of the core values of this event.

MCH2022 is the successor of a string of similar events happening every four years since 1989.
These are GHPHEUHIPHALWTHHAROHM and SHA.

I’ve bin to several of these big events. Besides these big events are many different smaller events (wannull, ne2000 etc).

First one i’ve been was HIP97. I went with Bigred at that time.
I had to get the tickets at that time, he didn’t had a handle at that time. It was Monique who came up with his new nick.

After HIP97 there was HAL2001 WTH2005 and OHM2013 which i was present.
HAL2001 the whole ICEcrew was present, WTH a part of them, OHM a few and i was with a few PRUTS friends.

Now i was with my girlfriend, AND with Bigred again!
Loads of fun and memories. Had not seen Bigred since a inbetween hacker party at my place.
So ’97 and now ’22 .. jeez 25 years!

So MCH, it was great again.
Loads of stuff to do and to see.
Weather was … okay. Two days where really hot, one day some light rain but a load of wind. Our neighbours tent collapsed, beer tents where reenforced.
First campsite with a supermarket!
Music stage was awesome, lasers and fire!

I went to a lot of talks, even my girlfriend found some she was interested in.

This was the last time i’ve brought my “Windows free zone tape”
This big roll of tape was used on many occasions.
I got this roll somewhere < 2000, I did a search but couldn’t find anything mentioning it on the web. Maybe some archive.org entry?

  • Starting a Home Computer Museum (which i almost did in the past)
  • streaming 360 video (going to try this with my Vuze XR Camera)
  • Non-Euclidean Doom: what happens to a game when pi is not 3.14159…
    (Really enjoyed this one)
  • Hacking the genome: how does it work, and should we?
  • And more

Besides the talks i’ve done some workshops:

  • Micropython on the badge (see my other post)
  • Kicad – PCB designing

Meanwhile we where looking at all the villages and hackerspaces. Loads of interesting people to meet. Like our neighbour two tents futher, he was also a home-brewer, and he brought a minifridge with beer taps connected to it.

When back at our tent or Bigreds Campervan, we talked about differences now and then. New technology, what we’ve been upto in the last years and tinkering, loads of tinkering.

I’ve brough a big plastic container with .. ehh “things to do ….”

  • My 6502, bigred helped me debugging the 16*2 display.
    (Luckily his campervan was packed with electronics!)
    We cannibalized one of his projects for a display, and re-flashed his eeprom programming arduino to test my display. ( The arduino i had to reflash later to program a rom he had given me for my 6502. )
    Other toys he gave me: Print for the programmer, and a C64 Cartridge print for Exrom and Game.
  • Mini C64 with a little screen and raspberry zero.
  • 5050 ledstrip (didn’t had time to reprogram this for our mood-light)
  • Handheld gamehat: Bigred found some old games he played when he was young
  • Mikrotik router, because i wanted to make a dmz for my girlfriends laptop. (MS)
  • Playing around with my Vuze XR camera
  • Huskycam, which i’m planning to use on a racetrack
  • DVB-T DAB FM Stick, got some hints and tips from Bigred.
    (Note to myself … fix the antenna!)
  • My Arduino touch bagpipe player with i2c
  • The wifi deauther, which has a display which i wanted to use to make a programmable clock for my 6502. Using a rotary encoder and the display to control the speed in Hz.
  • I spend many hours playing with the Badge and Kicad

Wrote some 6502 assembly, arduino sketches, php, bash and micropython.

While playing around with the badge i got some things working easily.
Spinning logo and blinky leds.
Next goal to achieve was, to get the gyroscope to control the angle of spinning.
Most of the code worked, but the gyro values stayed zero!
(After many hours …. you have to start/enable the chip/measurements on the bno055 first! .. duh! )

I didn’t had my dev directory from my main battlestation synced in my nextcloud, so changing things for the 6502 was a b*tch.
Used vasm and acme to generate a bin file to use to fill the rom.
Didn’t like the eeprom programmer program, because i could not easily check the rom contents.
Have to look into that later on.

While learning to use Kicad, which i only had been using to draw schematics (besides fritzing) , i learned to create a pcb.
Which gave me the idea to make a print for the power-on-reset for the 6502. Which is going to be the first PCB by ordering, instead of the old skool messing around with DIY print making. (see next post)

….. Oh, why my display was not working?
I even connected my 8bit logic analyzer to the pins of the display.

Everything was correct.
But i didn’t use a variable resistor for the contrast. Just a simple resistor i could find. Luckily … bigreds stash.
All those hours debugging, all for one resistor!
(I have to mention, we had a suspicion halfway. But it was too hot and we where too lazy to go to Bigred’s campervan, to get a potentiometer. )

Goodies from Bigred

Sound Firewall

See also 2nd Firewall 2013 and Led Firewall
https://www.henriaanstoot.nl/2013/08/03/ohm-2013-hackerevent/

While partying @ HAL2001, a hackers event, Venom and I made a Soundfirewall.

We had a little DMZ, with our servers.
This was protected by a iptables firewall.

Our idea was to get a sound notification on every (interesting) network packet the firewall dropped.

So we made this: (At the bottom are the sound definitions.)
Example of the sound we heared whole day.

#use strict;
#       @(#)    First Edit: Bas
#       @(#)    Last Edit: Fash

use POSIX ":sys_wait_h";
use vars qw(%Msg_Rec);

$SIG{'TERM'} = $SIG{'HUP'} = 'goodbye';
$SIG{'CHLD'} = 'IGNORE';

## Constants
my $BELL   = "";
my $MAILER = "/usr/sbin/sendmail";
my $WRITE  = "/usr/bin/write";
$/ = "
";

autoflush STDOUT;

sub goodbye {
  $| = 0;

  close_pipe_if_open();
  exit(0);
}

#
# in_range($range, $number) 
# returns 1 if $number is inside $range, 0 if not
#
sub in_range {
  my $range = shift;
  my $num = shift;

  foreach my $f (split(/,/, $range)) {
    if ($f =~ /-/) {
      my ($low,$high) = split(/-/, $f);
      return 1 if ($low <= $num and $num <= $high);
    } elsif ($f == $num) {
      return 1;
    }
  }
  return 0;
}

# 
# inside_time_window($days,$hours)
# returns 1 if inside window, 0 if outside window
#
sub inside_time_window {
  my $range = shift;
  my($days, $hours) = split(/:/, $range);

  my ($hr, $wday) = (localtime(time))[2,6];

  if (($days eq '*' or in_range($days, $wday))
      and ($hours eq '*' or in_range($hours, $hr))) {
    return 1;
  } else {
    return 0;
  }
}

  
print "\n*** swatch-3.0.1 (pid:6826) started at " . `/bin/date` . "\n";

  
use Date::Calc qw(:all);

sub parse_dot {
  my $message = shift;
  my $dot_loc = shift;
  my @dot = ();
  my @ranges = split(/:/, $dot_loc);

  foreach my $range (0..$#ranges) {
    if ($ranges[$range] != -1) {
      my ($begin, $end) = split(/-/, $ranges[$range]);
      $dot[$range] = substr($message, $begin, ($end - $begin + 1));
    }
  }

  return @dot;
}

my ($date_loc, $time_loc) = ("-1:0-2:4-5", "7-8:10-11:13-14");
my %months = (
              Jan => 1,
              Feb => 2,
              Mar => 3,
              Apr => 4,
              May => 5,
              Jun => 6,
              Jul => 7,
              Aug => 8,
              Sep => 9,
              Oct => 10,
              Nov => 11,
              Dec => 12
             );

# Returns an array of year, month, day, hours, minutes, and seconds.
#
sub YMDHMS {
  my $string = shift;
  my $year_today = (Today())[0];

  my ($y, $m, $d) = parse_dot($string, $date_loc);
  my ($hrs, $mins, $secs) = parse_dot($string, $time_loc);
  if (length($y) eq 0) { $y = (Today())[0] };

  return ($y, $months{$m}, $d, $hrs, $mins, $secs);
}

sub new_msg {
  my $use = shift;
  my $msg = shift;
  my $count = shift;
  my @delta = @_;
  my $delta;
  if ($delta[0] == 0) {
    $delta = sprintf("%d:%.2d:%.2d", $delta[1], $delta[2], $delta[3]);
  } else {
    $delta = sprintf("$delta[0] day%s %d:%.2d:%.2d", $delta[0] > 1 ? 's' : '',
                    $delta[1], $delta[2], $delta[3]);
  }
  if ($use eq 'regex') {
    return "$count $msg regular expressions in $delta";
  } else {
    return "$count in $delta: $msg";
  }
}

#
# Stores message information in 
#    $Msg_Rec = (
#      {<truncated message>|<pattern>} => {
#        dhms => [ array ], # days,hours,minutes,seconds
#        count => integer,

sub throttle {
  my %opts = (
              KEY       => $_,
              CUT_MARKS => [ "0:16" ], # not used yet
              USE       => 'message',
              @_
             );

  my $msg = $opts{'KEY'};
  my $use = $opts{'USE'};
  my @ymdhms = YMDHMS($msg);
  my $key;
  my @min_dhms_delta = split(/(\s+|:)/, $opts{'MIN_DELTA'});

  foreach my $i (0..$#min_dhms_delta) {
    # strip out unwanted element
    splice (@min_dhms_delta, $i, 1) if ($min_dhms_delta[$i] eq ":");
  }

  if ($use eq 'regex') {
    $key = $opts{'REGEX'};
  } else {
    $key = substr($msg, 16);
    $key =~ s/\[\d+\]/[PID]/;
  }

  while ($#min_dhms_delta < 3) {
    unshift(@min_dhms_delta, 0); # make sure that the dhms array is full
  }

  if (exists $Msg_Rec{$key} and defined $Msg_Rec{$key}->{ymdhms}) {
    my $passed = 1;
    $Msg_Rec{$key}->{count}++;
    if ($ymdhms[1] > $Msg_Rec{$key}->{ymdhms}[1]) { $ymdhms[0]--; }

    my @delta_dhms = Delta_DHMS(@{$Msg_Rec{$key}->{ymdhms}}, @ymdhms);
    foreach my $i (0..$#min_dhms_delta) {
      $passed = 0 if ($delta_dhms[$i] < $min_dhms_delta[$i]);
      last unless ($delta_dhms[$i] == $min_dhms_delta[$i]);
    }    
    if ($passed) {
      my $new = '';
      $new = new_msg($use, $key, $Msg_Rec{$key}->{count}, @delta_dhms);
      $Msg_Rec{$key}->{ymdhms} = [ @ymdhms ];
      $Msg_Rec{$key}->{count} = 1;
      return $new;
    } else {
      return '';
    }
  } else {
    my $rec;
    $rec->{ymdhms} = [ @ymdhms ];
    $Msg_Rec{$key} = $rec;
    return $msg;
  }
}


##
## ACTION SUBROUTINES
##

my %text_modes = (
  "black"       => "\033[30;1m",
  "red"         => "\033[31;1m",
  "green"       => "\033[32;1m",
  "yellow"      => "\033[33;1m",
  "blue"        => "\033[34;1m",
  "magenta"     => "\033[35;1m",
  "cyan"        => "\033[36;1m",
  "white"       => "\033[37;1m",
  "black_h"     => "\033[40;1m",
  "red_h"       => "\033[41;1m",
  "green_h"     => "\033[42;1m",
  "yellow_h"    => "\033[43;1m",
  "blue_h"      => "\033[44;1m",
  "magenta_h"   => "\033[45;1m",
  "cyan_h"      => "\033[46;1m",
  "white_h"     => "\033[47;1m",
  "bold"        => "\033[1m",
  "blink"       => "\033[5m",
  "inverse"     => "\033[7m",
  "normal"      => "\033[0m",
  "underscore"  => "\033[4m",
);
  
sub echo {
  my %args = (
              'MODES' => [ 'normal' ],
              @_
             );

  return if (exists($args{'WHEN'}) and not inside_time_window($args{'WHEN'}));
  
  if ($args{'MODES'}[0] eq 'random') {
    my @mode_names = keys %text_modes;
    print $text_modes{$mode_names[rand $#mode_names]};
  } else {
    foreach my $mode (@{$args{'MODES'}}) {
      print $text_modes{$mode};
    }
  }
  print $args{'MESSAGE'};
  print $text_modes{'normal'};
  print "\n";
}

#
# ring_bell(args) -- send x number of control-G characters to the output.
#
sub ring_bell {
  my %args = (
              'RINGS' => 1,
              @_
             );
  my $sun_terminal = (`uname -s` eq 'SunOS\n');
  
  return if exists($args{'WHEN'}) and not inside_time_window($args{'WHEN'});
  
  my $bells = $args{'RINGS'};
  for ( ; $bells > 0 ; $bells-- ) {
    print $BELL;
    sleep 1 if $sun_terminal; # SunOS needed this. Not sure about Solaris though
  }
}

#
# exec_command(args) -- fork and execute a command
#
sub exec_command {
  my %args = (@_);
  my $exec_pid;
  my $command;

  if (exists $args{'COMMAND'}) {
    $command = $args{'COMMAND'};
  } else {
    warn "$0: No command was specified in exec action.\n";
    return;
  }

  return if exists($args{'WHEN'}) and not inside_time_window($args{'WHEN'});

 EXECFORK: {
    if ($exec_pid = fork) {
      waitpid(-1, WNOHANG);
      return;
    } elsif (defined $exec_pid) {
      exec($command);
      } elsif ($! =~ /No more processes/) {
        # EAGAIN, supposedly recoverable fork error
        sleep 5;
        redo EXECFORK;
      } else {
        warn "$0: Can't fork to exec $command: $!\n";
      }
  }
  return;
}


{
  my $pipe_is_open;
  my $current_command_name;
  #
  # send_message_to_pipe -- send text to a pipe.
  #
  # usage: &send_message_to_pipe($program_to_pipe_to_including_the_vertical_bar_symbol,
  #               $message_to_send_to_the_pipe);
  # 
  
  sub send_message_to_pipe {
    my %args = (@_);
    my $command;

    if (exists $args{'COMMAND'}) {
      $command = $args{'COMMAND'};
    } else {
      warn "$0: No command was specified in pipe action.\n";
      return;
    }

    return if exists($args{'WHEN'}) and not inside_time_window($args{'WHEN'});

    # open a new pipe if necessary
    if ( !$pipe_is_open or $current_command_name ne $command ) {
      # first close an open pipe
      close(PIPE) if $pipe_is_open;
      $pipe_is_open = 0;
      open(PIPE, "| $command") 
        or warn "$0: cannot open pipe to $command: $!\n" && return;
      PIPE->autoflush(1);
      $pipe_is_open = 1;
      $current_command_name = $command;
    }
    # send the text
    print PIPE "$args{'MESSAGE'}";

    if (not exists $args{'KEEP_OPEN'}) {
      close(PIPE) if $pipe_is_open;
      $pipe_is_open = 0;
    }
  }

  #
  # close_pipe_if_open -- used at the end of a script to close a pipe
  #     opened by &pipe_it().
  #
  # usage: &close_pipe_if_open();
  #
  sub close_pipe_if_open {
    if ($pipe_is_open) {
      close(PIPE);
    }
  }
}


#
# send_email -- send some mail using $MAILER.
#
# usage: &send_email($addresses_to_mail_to);
#
sub send_email {
  my $login = (getpwuid($<))[0];
  my %args = (
              'ADDRESSES' => $login,
              'SUBJECT' => 'Message from Swatch',
              @_
             );

  return if exists($args{'WHEN'}) and not inside_time_window($args{'WHEN'});

  my $addresses = $args{'ADDRESSES'};
  $addresses =~ s/:/,/g;

  if ($MAILER eq '') {
    warn "ERROR: $0 cannot find a mail delivery program\n";
    return;
  }

  open(MAIL, "| $MAILER $addresses")
    or warn "$0: cannot open pipe to $MAILER: $!\n" && return;

  print MAIL "To: $addresses\n";
  print MAIL "Subject: $args{SUBJECT}\n\n";
  print MAIL "$args{'MESSAGE'}\n";
  close(MAIL);
}


#
# write_message -- use $WRITE to send a message logged on users.
#
sub write_message {
  my %args = (@_);

  return if exists($args{'WHEN'}) and not inside_time_window($args{'WHEN'});

  if ($WRITE eq '') {
    warn "ERROR: $0 cannot find the write(1) program\n";
    return;
  }

  if (exists($args{'USERS'})) {
    foreach my $user (split(/:/, $args{'USERS'})) {
      send_message_to_pipe(COMMAND => "$WRITE $user 2>/dev/null", 
                           MESSAGE => "$args{'MESSAGE'}\n");
    }
  }
}

use File::Tail;
my $Filename = '/var/log/ulog/syslogemu.log';
my $File = File::Tail->new(name=>$Filename, maxinterval => 1, interval => 1);
if (not defined $File) {
    die "/usr/local/bin/swatch: cannot read input \"$Filename\": $!\n";
}

LOOP: while (defined($_=$File->read)) {

    chomp;
    my $sanitized_ = $_;
    @_ = split;
    
    # quote all special shell chars
    $sanitized_ =~ s/([;&\(\)\|\^><\$`'\\])/\\$1/g;
    my @sanitized_ = split(/\s+/, $sanitized_);
    if (/INVALID|REPEATED|INCOMPLETE:LOGIN/) {
        echo('MODES' => [ "bold", ], 'MESSAGE' => "$_", );
        ring_bell('RINGS' => "3", );
        next;
    }

    if (/(panic|halt)/) {
        echo('MESSAGE' => "$_", );
        ring_bell();
        next;
    }

    if (/Regents/) {
        echo('MODES' => [ "bold", ], 'MESSAGE' => "$_", );
        ring_bell();
        next;
    }

    if (/ipfw:.*Deny ICMP:8.0/) {
        echo('MODES' => [ "bold", ], 'MESSAGE' => "$_", );
        exec_command('COMMAND' => "mpg123 -q /root/wavs/drip.wav &", );
        next;
    }

    if (/ipfw:.*Deny TCP .*:6000/) {
        echo('MODES' => [ "bold", ], 'MESSAGE' => "$_", );
        exec_command('COMMAND' => "mpg123 -q /root/wavs/camera.wav &", );
        next;
    }

    if (/ipfw:.*Deny UDP .*:513/) {
        echo('MODES' => [ "bold", ], 'MESSAGE' => "$_", );
        exec_command('COMMAND' => "mpg123 -q /root/wavs/flush.wav &", );
        next;
    }

    if (/ipfw:.*Deny TCP .*:21/) {
        echo('MODES' => [ "bold", ], 'MESSAGE' => "$_", );
        exec_command('COMMAND' => "mpg123 -q /root/wavs/vault.wav &", );
        next;
    }

    if (/PROTO=TCP .*DPT=80/) {
        echo('MODES' => [ "bold", ], 'MESSAGE' => "$_", );
        exec_command('COMMAND' => "mpg123 /root/wavs/tcp80.mp3 &", );
        next;
    }
    if (/PROTO=TCP .*DPT=23/) {
        echo('MODES' => [ "bold", ], 'MESSAGE' => "$_", );
        exec_command('COMMAND' => "mpg123 /root/wavs/tcp23.mp3 &", );
        next;
    }

    if (/UDP .*=1300007/) {
        echo('MODES' => [ "bold", ], 'MESSAGE' => "$_", );
        exec_command('COMMAND' => "mpg123 /root/wavs/udp137.mp3 &", );
        next;
    }

    if (/PROTO=ICMP/) {
        echo('MODES' => [ "bold", ], 'MESSAGE' => "$_", );
        exec_command('COMMAND' => "mpg123 /root/wavs/ping.mp3 &", );
        next;
    }

    if (/.*/) {
        echo('MESSAGE' => "$_", );
        next;
    }

}

Made a webinterface for my DIY webcam

Using a steppermotor controller with two motors. A video capturing device (videoblaster) and a mini B/W camera.

  • Up/down/left/right and diagonal
    • Red double speed green single speed
  • Reset view
  • 2 Presets with save and recall
Setup with parallel cable

Written software in html and some CGI scripts.
Perl and C.

#include <asm/io.h>

# C Code for moving left

int main(int agrc,char agrv[])
{
  int i,wachten;
  int richting1[8]={0x27,0x2d,0x1c,0x0d,0x03,0x09,0x38,0x29};
  int richting2[8]={0x29,0x38,0x09,0x03,0x0d,0x1c,0x2d,0x27};
  ioperm(0x378,3,1);
  ioperm(0x37a,3,1);
  wachten=100;


for (i=0; i<=7; i=i+1)
        {
        outb(richting2[i], 0x378);
        outb(1, 0x37a);
        usleep(wachten);
        outb(0, 0x37a);
        usleep(wachten);
        outb(1, 0x37a);
        usleep(wachten);
        }

 return(0);
}
#!/usr/bin/perl
# Perl CGI script 

# Uses 204 no content trick to stay on same page
use LWP::Simple;
my $img = get ('http://10.1.0.1/cgi-bin/left.cgi');
print "Status: 204 No content\n\n";

Streaming video was done using progressive JPG push.
Later i used the capturing command in the loop below.

#!/bin/sh

# push jpg, and update after 1sec
# output mime header

echo Content-type: multipart/x-mixed-replace;boundary=--WebcamRules\n
echo
echo --WebcamRules

# create stream

while true; do
   echo Content-type: image/jpeg
   echo
   cat /var/lib/httpd/htdocs/webcam.jpg
   echo
   echo --WebcamRules

   sleep 1
done

Steppermotor card was using a parallel port.

Aluminum machined part by Joost

Old skool Home Automation & GPC

The date of this post is when we worked on GMC’s GPC, but i’ll post some other own made hardware related to domotica.

GPC Original Page: https://gpc.metro.cx/gpc/README

This DIY home automation was written by GMC in C.
Later we made little microcontroller prints, which could control/switch lights and more.

PIC16x84

We uses GPASM as assembler

One of my schematics
What is this?
=============

 This is the Global Premises Control package. It is intended to be a
complete solution to the DIY home automation. It provides you with a
daemon which will centralize all control functions, and some custom
programs for sound, remote control and things like that.
 The first steps to realizing the goal was made by Koen Martens. He wrote
the first daemon and made the first support programs. Other people got
interested and ported the GPC package to their homes. Since then it seemed
wise to coordinate development to prevent from having three different
versions of the package. It is currently under development and is far from
complete.

History
=======

 15-03-98 - The first initiative
	    With the help of Henri Aanstoot and Marco Geels the first
	    cables were mounted in the ceiling at Waalstraat 136. This
            involved re-dedicating some high voltage lines for the low 
	    voltage used by GPC equipment.
	    The next few days Koen Martens spend his time writing software
	    to switch on the lights (which was not possible without
	    software anymore :). This software was very rudimentry and 
	    did not feauture the daemon yet.
 28-03-98   Version 1.0 was born.
	    The need for a global way to control the premises arose, and
	    Koen Martens decided to write a daemon which would control the
	    input and output lines, with support programs for the logic.
	    This resulted in global, the gpc daemon. 
	    Running on different servers there were programs to control
	    lights and lightswitches (light_control), sound (sound) and
	    the alarm clock (wakeup). 
 10-06-98   Version 2.0 (r0.2.0) was born. 
	    The support programs containing any logic had vanished,
	    instead the daemon had all the logic encoded in it.    
 03-07-98   Version 2.0 still.
	    - Added remote control receiver code.
 29-11-98   GPC r0.3.0
	    - Started coordinated development
 11-12-98   GPC r0.3.1
	    - Security support included, providing a (basic) interface
	      for protecting variables with passwords on a security level 
	      clearance basis.
	    - Global notify protocol added, clients can now register one
	      or more variables. This makes the old (0.3.0) polling method
	      obsolete thus reducing the network load dramatically.
	    - Logging library added.

Development
===========

 The development is done on the following beta sites:

 - Subnet
	Location	: Waalstraat 136, Enschede, Netherlands
	Site coordinator: Koen Martens AKA gmc (gmc@freemail.nl)
	Site description: Single floor appartment
			  3 occupants (1 human, 2 rats)
			  P60 32MB RAM running linux
			  486 8MB RAM running FreeBSD
			  486 8MB RAM running linux
			  DEC Writer
			  WYSE terminal
			  The 486 linux machine has the daemon, and is 
			  hooked up to the premises.
			  The P60 has a sound card and a RC receiver.
 - Lip-on-ice
	Location	: Lipperkerkstraat 321, Enschede, Netherlands
	Site coordinator: Willem-Jan Faber AKA aloha AKA xtz ( And Henri Aanstoot AKA Fash)
			  (w-jfaber@freemail.nl)
	Site description: Three floor house
			  Four occupants (3 male, 1 female)
			  Connected to three other premises.
			  Computer list not yet in!
			  
 - Venom
	Location	: P. Mondriaanstraat ??, Almelo, Netherlands
	Site coordinator: Sebastiaan Smit AKA venom (wssmit@freemail.nl)
	Site description: Three floor house
			  Three occupants
			  4 computers

 If you would like to join the development, mail me at gmc@freemail.nl.


In progress
===========

 The following projects are in progress right now:
	- A script language to describe the control logic for the daemon
		Koen Martens
	- An cgi interface for the http connectivity
	- Support for sharing variables on multiple daemons

Usage
=====

 Use is for your own risk. We can not be held responsible for any damage
resulted from running any of this software.
 Keeping that in mind, usage is very simple but work needs to be done on
the documentation :)

DIY door sensor using a bend CDROM and a sensor i got

I’d would send a signal to our computers and playing a sound sample on our sound system. Also a IRCbot named (lampje) would mention “Backdoor open” in our own channel. (We where running our own IRC servers, interconnected .. because we can. A average of 3 Clients per server sound the way to go .. LOL )
Lampje the IRCbot also controlled the livingroom light and more.

ICH Meeting

Internet Club Hengelo ..

Later we started Intranet Club Enschede, which was the birth of Icecrew.

Some explained website building, browsing the net, and tools to use.

Bigred and me build the network, and services which where used for demonstrations.
We also helped with solving network related problems.

Interview Radio Oost

Above was done with my little DIY streaming webcam.
(progressive push jpg cgi script, see other post)

I found some text/log about this day
(found a scanned item first, then i used namazu .. i love namazu, it found the original ascii text file.
(Dutch only)

Zaterdag 20 September 1997
--------------------------

's ochtens om 8 uur wakker gemaakt door Marco.
Ik was nog een beetje ziek, maar toch maar de 2 pc's ingepakt.
(die van Miko en die van mij)
Ook Marco z'n pc met cd-brander stond al in de auto.
Omdat het een kleine opel kadett was moesten we behoorlijk proppen.
Ondertussen had ik al overgegeven maar ik kon moeilijk thuisblijven want ik moest het netwerk voor die dag nog aan de praat zien te krijgen.
Na een 'bumpy ride' in de Kadett waren we eindelijk op de plaats van bestemming.

Hier aangekomen bleek dat waar we de pc's neer moesten zetten, toch verder van de ISDN-aansluiting was als verwacht.
Moest ik nu mijn pc (welke als proxy-server/firewall moest werken) nu in dit kantoortje staan en dan een coax naar de rest van de pc's of moesten we voor een lang ISDN kabel zorgen?
Omdat de Webcam aan mijn pc zat moesten we eigenlijk een langere ISDN kabel hebben.
(Het was ook nog een probleem met de ISDN aansluitingen omdat de beide aansluitingen die de PTT had aangelegd al bezet waren i.v.m. de telefoonaansluitingen)
Nadat we 1 van de aansluitingen eruit hadden getrokken bleek dat he helft van de telefoons in het gebouw niet meer werken.

Na bij de PTT kabel's te hebben gekocht (1x 10 meter en 1x 25 meter plus en tussenstukje 62 gulden nogwat)
Kon ik eindelijk beginnen met het opzetten van de proxy server.

(Ondertussen nog even iemand van een netwerk-kaart voorzien en andere problemen opgelost)
Ook de netwerk instellingen moesten marco en ik bij iedereen behalve Miko en mijzelf veranderen.
(Komt er ook nog 1 zeuren over Office enzo)

Na wat aanpassingen werkte de proxy-server en de webcam.
Ook de http-server op Miko's pc werkte tegelijkertijd.

We werden ook nog geinterviewed door radio-oost ofzo. Dit wilden we tegelijkertijd via de webcam op internet laten zien, maar dat kon niet want die radio-meneer moest
zijn microfoon via de telefoon laten werken om rechtstreeks in de uitzending te komen.
Dus de proxy-server maar even uitgezet en het interview als avi opgenomen.

Later nog een website gemaakt met wat foto's van die dag erop.

Voor de volgende keer moet ik wel zorgen dat ik ook Irc en Mail via de proxy kan laten werken.

Op de terugweg nog een paar keer problemen gehad met de auto, deze viel zomaar uit.
Na met een startkabel tegen de stuurkolom de auto weer aan 't starten te hebben gekregen.
Liet marco de startkabel maar tussen de deur van de auto, zo kon hij nog een paar keer de auto simpel starten door de startkabel (welke van onder de moterkap kwam) tegen de stuurkolom te houden.
Website with pictures, avi part probably contained the streaming webcam part