Home

Just another post.

Leave a comment

Chit chat

======

Converting the nslu2 back to the original firmware. Oops, delaying that idea.

Lost a drive that was using arch linux.  Worked fine the last time I used it. Replaced it with a drive that has Debian. At least the machine is still being used.  Not a good week also lot a Raspberry Pi.

Had to put on a new ends on a few network cables. Once you  have done enough of them, you never forget the wo-o-wg-bl-wbl-g-wbr-br aka

white-orange orange white-green blue white-blue green white-brown brown

Moved some c source files over to the pogoplug and tested compiling some c code.

Brother is getting the android 5 update. Android 5 without hardwire access is a fail.

Getting close to 1.5 million views at http://www.instructables.com/member/computothought

—————————————–

To convert a web page for use with the arduino, you will need to add a preface and an ending to each line of code.

Original code:

<html>
<body>
This is a text message.
</body>
</html>

Using vim add a beginning with: :%s!^!client.println(\”!

client.println(“<html>
client.println(“<body>
client.println(“This is a text message.
client.println(“</body>
client.println(“</html>

Then using vim add an ending with: :%s/$/\”);/

client.println(“<html>”);
client.println(“<body>”);
client.println(“This is a text message.”);
client.println(“</body>”);
client.println(“</html>”);

Result:

Also:

client.println(“”);
client.println(“This is a test of the arduino.”);
client.println(“”);
client.println(“<pre>”);
client.println(”                                 ___________”);
client.println(”                                [___________]”);
client.println(”                                 {=========}”);
client.println(”                               .-*         *-.”);
client.println(”                              /               \\”);
client.println(”                             /_________________\\”);
client.println(”                             |   _  _   _      |”);
client.println(”                             ||\\(_ |_)||_)||\\ ||”);
client.println(”            ,.–.   ,.–.    ||~\\_)|  || \\|| \\||”);
client.println(”           // \\  \\ // \\  \\   |_________________|”);
client.println(”           \\\\  \\ / \\\\  \\ /   |                 |”);
client.println(”            `*–*   `*–*    ‘—————–‘”);
client.println(“</pre>”);

Your code should now work within an ethernet sketch. The rest is up to your imagination.

—————————————–

Try at your own risk. Your system could be damaged.

Plug goes into a sound card output. Of course, you will need an AM capable radio to receive the transmissions. Dial needs to be set at or near 100x10khz. There was several strong competing stations where we tested this project.

—————————————–

Decided to make a sd card with arch linux using these instructions:

SD Card Creation
Replace sdX in the following instructions with the device name for the SD card as it appears on your computer.

  1. Start fdisk to partition the SD card:
    fdisk /dev/sdX
  2. At the fdisk prompt, delete old partitions and create a new one:
    1. Type o. This will clear out any partitions on the drive.
    2. Type p to list partitions. There should be no partitions left.
    3. Type n, then p for primary, 1 for the first partition on the drive, press ENTER to accept the default first sector, then type +100M for the last sector.
    4. Type t, then c to set the first partition to type W95 FAT32 (LBA).
    5. Type n, then p for primary, 2 for the second partition on the drive, and then press ENTER twice to accept the default first and last sector.
    6. Write the partition table and exit by typing w.
  3. Create and mount the FAT filesystem:
    mkfs.vfat /dev/sdX1 mkdir boot mount /dev/sdX1 boot
  4. Create and mount the ext4 filesystem:
    mkfs.ext4 /dev/sdX2 mkdir root mount /dev/sdX2 root
  5. Download and extract the root filesystem (as root, not via sudo):
    wget http://archlinuxarm.org/os/ArchLinuxARM-rpi-latest.tar.gz
  6.  sudo apt-get install bsdtar
  7. bsdtar -xpf ArchLinuxARM-rpi-latest.tar.gz -C root sync
  8. Move boot files to the first partition:
    mv root/boot/* boot
  9. Unmount the two partitions:
    umount boot root
  10. Insert the SD card into the Raspberry Pi, connect ethernet, and apply 5V power.
  11. Use the serial console or SSH to the IP address given to the board by your router. The default root password is ‘root’.
  12. Once you log in be sure to update the  system with pacman -Syu

—————————————–

You can take software from years even decades ago and still reuse it. For example, found some accounting source code originally written as early as the 1970’s that can be compiled and used on present day systems. Albeit that the software needs some polish to be presentable by today’s standards, it still works just as well.

Account setup:

Then you can enter some data:

Lastly, you can views the results of your entries say in a simple t-account format:

The datafile:

$ cat bizness

02052015               XX X X X X X XXXXXXXXassets             XXXXXXXXXXXXXXXliabilities        XXXXXXXXXXXXXXXcapital            XXXXXXXXXXXXXXXincome             XXXXXXXXXXXXXXXexpenses           XXXXXXXXXXXXXXXunused             XXXXXXXXXXXXXXXunused             XXXXXXXXXXXXXXXincome/expense sum.XXXXXXXXXXXXXXXCash               d�D c Cd@�D czCc�c D

cHCXXXXXXXXSupplies           d C    c�BXXXXXXXXXXXXXEquipment          dzDXXXXXXXXXXXXXXAccounts payable   czd DXXXXXXXXXXXXXNotes Payable      XXXXXXXXXXXXXXXCapital – owner    c�DXXXXXXXXXXXXXXDrawing – owner

dHCXXXXXXXXXXXXXXFee income         c@�DXXXXXXXXXXXXXXRent               dzCXXXXXXXXXXXXXXSupplies expense       d�BXXXXXXXXXXXXXXTelephone Expense  d�BXXXXXXXXXXXXXX

What software can you put back to work?

—————————————–
With more and more people using the command line, changing permissions is a must. Chmod (chmod) is used to change permissions of a file. Do not use it that much except when setting permissions on the .ssh folder or on a web server application directories

i.e.
$ sudo chmod -R 755 appdirectory

or

$ chmod 700 ~/.ssh
$ chmod 600 ~/.ssh/*

Explanation examples:

Permissions Command
User Group World
rwx rwx rwx chmod 777 filename
rwx rwx r-x chmod 775 filename
rwx r-x r-x chmod 755 filename
rw- rw- r– chmod 664 filename
rw- r– r– chmod 644 filename

r = readable  w = writable x = executable  – = no permission

Here is another way of looking at it:

ugw function
400 r– read by owner
040 -r- read by group
004 –r read by anybody (other)
200 w– write by owner
020 -w- write by group
002 –w write by anybody
100 x– execute by owner
010 -x- execute by group
001 –x execute by anybody

To get a combination, just add them up. For example, to get read, write, execute by owner, read, execute, by group, and execute by anybody, you would add 400+200+100+040+010+001 to give 751.

There is also a nice web based calculator you can use on a web page of your own making: http://wsabstract.com/script/script2/chmodcal.shtml

Note: Some people like to use:
chmod ugo=rwx myfile
Where the nerds use:
chmod 777 myfile

—————————————–

Some experimental mysql database setup scripts. Should be able to use then with Mariadb. (USE AT YOUR OWN RISK!)Original script:#!/bin/bash EXPECTED_ARGS=3 E_BADARGS=65 MYSQL=`which mysql`
#Danger do not use GRANT ALL ON *.*
Q1=”CREATE DATABASE IF NOT EXISTS $1;” Q2=”GRANT ALL ON *.* TO ‘$2’@’localhost’ IDENTIFIED BY ‘$3′;” Q3=”FLUSH PRIVILEGES;” SQL=”${Q1}${Q2}${Q3}” if [ $# -ne $EXPECTED_ARGS ] then echo “Usage: $0 dbname dbuser dbpass” exit $E_BADARGS fi $MYSQL -uroot -p -e “$SQL”To use it, just run:
./createdb testdb testuser secretpassSomeone’s modified script:#!/bin/bash

BTICK=’`’
EXPECTED_ARGS=3
E_BADARGS=65
MYSQL=`which mysql`
Q1=”CREATE DATABASE IF NOT EXISTS ${BTICK}$1${BTICK};”
Q2=”GRANT ALL ON ${BTICK}$1${BTICK}.* TO ‘$2’@’localhost’ IDENTIFIED BY ‘$3′;”
Q3=”FLUSH PRIVILEGES;”
SQL=”${Q1}${Q2}${Q3}”
if [ $# -ne $EXPECTED_ARGS ]
then
echo “Usage: $0 dbname dbuser dbpass”
exit $E_BADARGS
fi
$MYSQL -uroot -p -e “$SQL”Using a little whiptail:

#!/bin/bash

USERNAME=$(whiptail –title “Mysql username” –inputbox “What is your Mysql username?” 10 60 $USER 3>&1 1>&2 2>&3)

exitstatus=$?
if [ $exitstatus = 0 ]; then
echo “Your pet name is:” $USERNAME
else
echo “You chose Cancel.” ; exit
fi

PASSWORD=$(whiptail –title “Mysql password” –passwordbox “Enter your password and choose Ok to continue.” 10 60 3>&1 1>&2 2>&3)

exitstatus=$?
if [ $exitstatus = 0 ]; then
echo “Your password is: XXXXXXXX”
else
echo “You chose Cancel.” ; exit
fi

DBNAME=$(whiptail –title “Database name” –inputbox “What is database name?” 10 60 DBNAME 3>&1 1>&2 2>&3)

exitstatus=$?
if [ $exitstatus = 0 ]; then
echo “Your pet name is:” $DBNAME
else
echo “You chose Cancel.” ; exit
fi
DBUSERNAME=$(whiptail –title “Database username” –inputbox “What is your database user name?” 10 60 DATABASEUSERNAME 3>&1 1>&2 2>&3)

exitstatus=$?
if [ $exitstatus = 0 ]; then
echo “Your pet name is:” $DBUSERNAME
else
echo “You chose Cancel.” ; exit
fi
DBHOST=$(whiptail –title “Database host name” –inputbox “What is your database host name?” 10 60 DBHOST 3>&1 1>&2 2>&3)

exitstatus=$?
if [ $exitstatus = 0 ]; then
echo “Your pet name is:” $DBHOST
else
echo “You chose Cancel.” ; exit
fi

DBPASSWORD=$(whiptail –title “Database password” –passwordbox “What is your database password?” 10 60 DBPASSWORD 3>&1 1>&2 2>&3)

exitstatus=$?
if [ $exitstatus = 0 ]; then
echo “Your password is : XXXXXXXX”
else
echo “You chose Cancel.” ; exit
fi

MYSQL=`which mysql`

Q1=”CREATE DATABASE IF NOT EXISTS $DBNAME;”
Q2=”GRANT ALL ON $DBNAME.* TO ‘$DBUSERNAME’@’$DBHOST’ IDENTIFIED BY ‘$DBPASSWORD';”
Q3=”FLUSH PRIVILEGES;”
SQL=”${Q1}${Q2}${Q3}”

$MYSQL -u $USER -p $PASSWORD -e “$SQL”

—————————————–

More on whiptail:

A message box shows any arbitrary text message with a confirmation button to continue. whiptail –title “<message box title>” –msgbox “<text to show>” <height> <width>

Example:

#!/bin/bash

whiptail –title “Message Box” –msgbox “Create a message box with whiptail. Choose Ok to continue.” 10 60

Screenshot from 2015-02-07 12:22:20

Create a Yes/No Box

One common user input is Yes or No. This is when a Yes/No dialog box can be used. whiptail –title “<dialog box title>” –yesno “<text to show>” <height> <width>

Example:

#!/bin/bash
if (whiptail –title “Yes/No Box” –yesno “Do you like computers (yes/no)?” 10 60)
then echo “Yes, you like computers. Exit status was $?.”
else echo “No, you do not like computers. Exit status was $?.”
fi

Optionally, you can customize the text for Yes and No buttons with “–yes-button” and “–no-button” options.

Example:

#!/bin/bash

if (whiptail –title “Test Yes/No Box” –yes-button “Free software” –no-button “Closed software” –yesno “Which do you like better?” 10 60)

then echo “You chose free software Exit status was $?.”

else echo “You chose closed software. Exit status was $?.”

fi

Screenshot from 2015-02-07 12:44:13

Example:

#!/bin/bash

if (whiptail –title “Test Yes/No Box” –yes-button “Free software” –no-button “Closed software” –yesno “Which do you like better?” 10 60)

then echo “You chose free software Exit status was $?.”

else echo “You chose closed software. Exit status was $?.”

fi

You saw the freeform and the password boxes in the previous section.

Create a Menu Box

When you want to ask a user to choose one among any arbitrary number of choices, you can use a menu box. whiptail –title “<menu title>” –menu “<text to show>” <height> <width> <menu height> [ <tag> <item> ] . . .

Example:

#!/bin/bash

OPTION=$(whiptail –title “Menu Dialog” –menu “Choose your option” 15 60 4 \ “1” “Grilled ham” \ “2” “Swiss Cheese” \ “3” “Charcoal cooked Chicken thighs” \ “4” “Baked potatos” 3>&1 1>&2 2>&3)

exitstatus=$?

if [ $exitstatus = 0 ];

then echo “Your chosen option:” $OPTION

else echo “You chose Cancel.”

fi

Screenshot from 2015-02-07 12:13:57

Create a Radiolist Dialog

A radiolist box is similar to a menu box in the sense that you can choose only option among a list of available options. Unlike a menu box, however, you can indicate which option is selected by default by specifying its status. whiptail –title “<radiolist title>” –radiolist “<text to show>” <height> <width> <list height> [ <tag> <item> <status> ] . . .

Example:

#!/bin/bash

DISTROS=$(whiptail –title “Test Checklist Dialog” –radiolist \ “What is the Linux distro of your choice?” 15 60 4 \ “Debian” “Stable Debian” ON \ “Ubuntu” “Copycat Debian” OFF \ “Centos” “Copycate Redhat” OFF \ “Mint” “Copycat Ubuntu/Debian” OFF 3>&1 1>&2 2>&3)

exitstatus=$?
if [ $exitstatus = 0 ];

then echo “The chosen distro is:” $DISTROS

else echo “You chose Cancel.”

fi

Screenshot from 2015-02-07 12:04:52

Create a Checklist Dialog

A checklist dialog is useful when you want to ask a user to choose more than one option among a list of options, which is in contrast to a radiolist box which allows only one selection. whiptail –title “<checklist title>” –checklist “<text to show>” <height> <width> <list height> [ <tag> <item> <status> ] . . .

Example:

#!/bin/bash

DISTROS=$(whiptail –title “Test Checklist Dialog” –checklist \ “Choose preferred Linux distros” 15 60 4 \ “Debian” “Stable Debian” ON \ “Ubuntu” “Debian copycat” OFF \ “Centos” “Redhat copycat” ON \ “Mint” “Copycat Ubuntu/Debian” OFF 3>&1 1>&2 2>&3)

exitstatus=$?

if [ $exitstatus = 0 ];

then echo “Your favorite distros are:” $DISTROS

else echo “You chose Cancel.”

fi

Screenshot from 2015-02-07 11:50:35

Create a Progress Bar

Another user-friendly dialog box is a progress bar. whiptail reads from standard input a percentage number (0 to 100) and displays a meter inside a gauge box accordingly. whiptail –gauge “<test to show>” <height> <width> <inital percent>

#!/bin/bash
PCT=0
(
while test $PCT != 100;
do
PCT=`expr $PCT + 10`;
echo $PCT;
sleep 1;
done; ) | whiptail --title "GAUGE" --gauge "Hi, this is a gauge widget" 20 70 0

Screenshot from 2015-02-07 11:40:30

By now, you must see how easy it is to create useful dialog boxes in an interactive shell script. Next time you need to write a shell script for someone, why don’t you try whiptail?

—————————————–

Another simple pasta favorite (fettucine made from scratch).

SUNP0031

Good day.

 

Artistic.

Leave a comment

Chit chat

======

Built another parallel port led thingy.

SUNP0026

Have a garbled text screen on the command line just use the reset command.

Set the time from he command line: Better to do it from the bios though.

sudo date [MMDDhhmm[[CC]YY][.ss]]

Screenshot - 01162015 - 07:48:34 AM

$ sudo date 011507482015

Have hidden files in your file selector, <ctrl>H will make them disappear or reappear as needed.

—————————————–

The Arduino is one of the neatest microcontrollers.  For something so simple, it can do an amazing amount of projects. One such project that interested me was the Digital melody project. If you have one the the Arduinos where the Atmel chip can be removed, you can make your own project without the board once the programming is done.

For this project, all you will need is the Arduino, usb cable (for programming), computer, some wires, optional 100 ohm resistor, and an old eight ohm speaker. Usually the back of speakers on the magnet have what resistance they are. So grab the old dead radio or the like that has a speaker and see what it has. Old personal computers are likely to have one too that you can borrow for a minute.

Now you need to build the circuit. It is minimal and you should be able to set it up quickly. Resistor adds safety for protecting the Arduino.

 

Set up up your Arduino for programming and load the Arduino IDE program into your computer. Then load in the Digital melody sample from the menu.

The instructions for your Arduino should tell you how to set up your board. Assuming your tools are set up properly, you can now compile and up load the sketch to your Arduino.

 

You should now hear a set of tones that sounds like it came from a cartoon. But what if you wanted to do your own tune. No problem. All you have to do is translate the notes and timing into your Arduino sketch. If you are unfamiliar with musical notation, you might want to get some help on this. The notation for a note might look something like this:

Then you need to have the note durations.

We decided to try doing Silent Night. Of course you need the sheet music to get the notes and the timing. The sketch will provide you with the information of how to translate the notes.

So we began doing our own translation using vim to record our results. Since this is 3/4 timing, things will be tricky.

Oops every thing is in lower case and we need to add the NOTE_ to the beginning of the notes. No problem. a g~~ will convert the letters to uppercase and a :%s!^!NOTE_! will the preface to the notes. So far so good. Now we need to separate the notes from the timings. So save the file.

$ cut -c-7  silentnight > notes-sn

and that gives us:

$ cat notes-sn
NOTE_G3
NOTE_A3
NOTE_G3
NOTE_E3
NOTE_G3
NOTE_A3
NOTE_G3
NOTE_E3
NOTE_D4
NOTE_D4


$ tr ‘\n’ ‘, ‘ < notes-sn > notes-sn.txt
$ sed -i ‘s/,/, /g; s/,\s\+/, /g’ notes-sn.txt
$ cat notes-sn.txt
NOTE_G3, NOTE_A3, NOTE_G3, NOTE_E3, NOTE_G3, NOTE_A3, NOTE_G3, NOTE_E3, NOTE_D4, NOTE_D4, NOTE_B3, NOTE_C4, NOTE_C4, NOTE_G3, NOTE_A3, NOTE_A3, NOTE_C4, … … …

Which can be easily cut and pasted into the sketch.

$ cut -d’-‘ -f2 silentnight  > notes-st

And that gives us

$ cat notes-st
3
8
4
1
3
8
4
1
1
4


Now to add the commas:

$ tr ‘\n’ ‘,’ < notes-st > notes-cs.csv

and that gives us which you can easily cut and paste into the sketch.

$ cat notes-cs.csv

3,8,4,1,3,8,4,1,1,4,1,1,4,1,1,…

To add spaces:
$ sed -i ‘s/,/, /g; s/,\s\+/, /g’ notes-cs.csv

cat notes-cs.csv
3, 8, 4, 1, 3, 8, 4, 1, 1, 4, 1, 1, 4, 1, … … …

You will also need to change this line for the total number of notes.

for (int thisNote = 0; thisNote < 8; thisNote++) {

More music!

—————————————–

In an earlier article, I talked about doing a minimal install of Debian linux (http://computoman.blogspot.com/2014/10/installing-debian.html). Decided to get out an old machine (Gateway Solo 3350 laptop) that this was done with. In playing with the machine, found that there was no sound drivers set up. Did the traditional install of the alsa not the pulse audio stuff.  This an old systeml

$ cat /proc/cpuinfo
processor    : 0
vendor_id    : GenuineIntel
cpu family    : 6
model        : 8
model name    : Pentium III (Coppermine)
stepping    : 3
microcode    : 0x7
cpu MHz        : 597.424
cache size    : 256 KB
fdiv_bug    : no
hlt_bug        : no
f00f_bug    : no
coma_bug    : no
fpu        : yes
fpu_exception    : yes
cpuid level    : 2
wp        : yes
flags        : fpu vme de pse tsc msr pae mce cx8 sep mtrr pge mca cmov pse36 mmx fxsr sse up
bogomips    : 1194.84
clflush size    : 32
cache_alignment    : 32
address sizes    : 36 bits physical, 32 bits virtual
power management:

Did I have a sound card?

$ lspci -v | grep audio
00:09.0 Multimedia audio controller: ESS Technology ES1988 Allegro-1 (rev 12)

Seems I do, so now to install the software.

$ sudo apt-get install alsa-base alsa-utils alsa-tools-gui alsaplayer-alsa  \ alsa-utils

Found the sound still did not work. did the usual modprobe and etc. with no luck. Time to do some research. Apparently I did not have the firmware installed for the sound card. In the article I found on the subject may not have pointed to the lastest firmware to I went to the source and downloaded the software. (alsa-firmware-1.0.28).

The came the process to install the firmware.

$ cd Downloads/
$ tar xvf alsa-firmware-1.0.28.tar.bz2′]
$ cd alsa-firmware-1.0.28/
$ ./configure
$ cd maestro3
$ make
$ su
# mkdir /lib/firmware/ess
# cp *fw /lib/firmware/ess
# modprobe -r snd-maestro3 ; modprobe snd-maestro3
# adduser $USER audio
# exit
$ exit

Now to test the setup.  Now to see what the settings are on the card. You will want to unmute any output devices and raise the volumes as needed.

$ alsamixer

$ aplay /usr/share/sounds/alsa/Noise.wav
$ speaker-test -t sine -f 440 -c 2
$ speaker-test -t wav -c 2

Now it seems I have sound for everything that happens. Yea!

—————————————–

Sometimes it is just nice to make a picture into an html file. Many pictures are in the .png format.  To use them to be converted to an html file they must first be converted to the .jpg format. For experimentation purposes start with a simple picture with a lot of contrast.

$ convert  speaker.png  speaker.jpg

speaker

By imbedding the picture in a page, it prevents you from having to keep lots of separate image files. Now let us convert it to an html page.
$ jconvert ws.png ws.jpg
jp2a –color –html –fill –background=light ws.jpg –output=hs.html

Screenshot - 01162015 - 07:05:01 AM

You can then go in and edit the html for further enchancement.

Screenshot from 2015-01-16 07:06:22

Let’s add a title and some ruler lines.

Screenshot from 2015-01-16 07:14:44

The rest is up to your imagination.

—————————————–

Bought the rc rechargeable batteries dirt cheap with the hope of using them with the microcontrollers such as the Raspberry Pi and the arduino, but they charged up to a bit higher value than I expected as the are rated for 4.5 volts.

SUNP0021SUNP0023

Thinking about using something like this to use as a voltage regulator. Probably will not work.

voltage45regulator

—————————————–

Got some old propeller chips as a gift.   Need to start building projects with it such as a C=64 clone.

SUNP0029

A circuit like this is what they say to start with.

PropConnections

The Simpleide software should be able to handle the programming for the cpu.

Screenshot from 2015-01-16 13:12:37

—————————————–

You never know when a simple cartoon can make a difference. Be sure and save all your doodles.

hardwareinstructs

macceronimaker

Tuxpaint is one of my favorite programs to draw with.

Screenshot from 2015-01-16 11:37:27Screenshot from 2015-01-16 11:38:15

—————————————–

Could of sworn, I already publish this article, but could not find it in a web search. Oh well here is a reprint:

Mom use to have an autoharp. She would play it once in a while. Kind of missed that old thing. Did not want to go out and purchase one. Saw a minimal bash script to let a linux box with sound emulate an autoharp. I modified that script to do a bit more.  It only has a few chords, but it is the most I will need for a while. Working on a super version,

Just like a regular autoharp, all you have to do is press a key for the chord sounding.

Use it. (super simple example):

On Top of Old Smokie

Old
(C)On top of old (F)Smokie, all covered in (C)snow,
I lost my true (G7 3)lover, by courtin' too (C)slow
(C)on top of old (F)Smokie, I went there to (C)weep
For a false hearted (G7)lover, is worse than a (C)thief

(C)A thief he will (F)rob you, and take what you (C)save
But a false hearted (G7)lover, will put you in your (C)grave
(C)On top of old (F)Smokie, all covered in (C)snow
I lost my true (G7)lover, by courtin' too (C)slow

(C) They'll hug you and (F)kiss you, then tell you more (C)lies
Than the crossties on the (G7) railroad, or the stars in the (C)skies
(C)on top of old (F)Smokie, all covered in (C) snow
I lost my true (G7)lover, by courtin' too (C)slow

New

(1) On top of old (4)Smokie, all covered in (1)snow,
I lost my true (3)lover, by courtin' too (1)slow
(1)on top of old (4)Smokie, I went there to (1)weep
For a false hearted (3)lover, is worse than a (1)thief

(1)A thief he will (4)rob you, and take what you (1)save
But a false hearted (3)lover, will put you in your (1)grave
(1)On top of old (4)Smokie, all covered in (1)snow
I lost my true (3)lover, by courtin' too (1)slow

(1) They'll hug you and (4)kiss you, then tell you more (1)lies
Than the crossties on the (3) railroad, or the stars in the (1)skies
(1)on top of old (4)Smokie, all covered in (1)snow
I lost my true (3)lover, by courtin' too (1)slow

Here is the source code that you can cut and paste into your favorite linux editor.


#!/bin/bash
#
# Script to emulate an autoharp.
#
while :
do
clear
echo "************************"
echo "* Mom's autoharp       *"
echo "************************"
echo "* [1] C major          *"
echo "* [2] A minor          *"
echo "* [3] G 7th            *"
echo "* [4] F major          *"
echo "* [5] D minor          *"
echo "* [6] E minor          *"
echo "* [7] E 7th            *"
echo "* [8] A 7th            *"
echo "* [9] C 7th            *"
echo "* [+] D 7th            *"
echo "* [-] G major          *"
echo "*                      *"
echo "* [0] Exit/Stop        *"
echo "************************"
echo
echo "Enter your menu choice [1-9, +, - or 0]: "
read -n 1 yourch
case $yourch in
1) play -n synth pl C2 pl E2 pl G2 pl C3 pl E3 pl G3 delay 0 .05 .1 .15 .2 .25 remix - fade 0 1.5 .1 norm -1  ;;
2) play -n synth pl A2 pl C2 pl E2 pl A3 pl C3 pl E3 delay 0 .05 .1 .15 .2 .25 remix - fade 0 1.5 .1 norm -1  ;;
3) play -n synth pl G2 pl B2 pl D2 pl F4 pl G3 pl B3 pl D3 pl F4 delay 0 .05 .1 .15 .2 .25 remix - fade 0 1.5 .1 norm -1  ;;
4) play -n synth pl F2 pl A2 pl C2 pl F3 pl A3 pl C3 delay 0 .05 .1 .15 .2 .25 remix - fade 0 1.5 .1 norm -1  ;;
5) play -n synth pl D2 pl F2 pl A2 pl D3 pl A3 pl F4 delay 0 .05 .1 .15 .2 .25 remix - fade 0 1.5 .1 norm -1  ;;
6) play -n synth pl E2 pl G2 pl B2 pl E3 pl B3 pl G4 delay 0 .05 .1 .15 .2 .25 remix - fade 0 1.5 .1 norm -1  ;;
7) play -n synth pl E2 pl G#2 pl B2 pl D2 pl E3 pl B3 pl G#4 delay 0 .05 .1 .15 .2 .25 remix - fade 0 1.5 .1 norm -1  ;;
8) play -n synth pl A2 pl C#2 pl E2 pl G2 pl A3 pl C#3 pl E3 pl G3 delay 0 .05 .1 .15 .2 .25 remix - fade 0 1.5 .1 norm -1  ;;
9) play -n synth pl C2 pl E2 pl G2 pl A#2  pl C3 pl E3 pl G3 pl A#3 delay 0 .05 .1 .15 .2 .25 remix - fade 0 1.5 .1 norm -1  ;;
+)  play -n synth pl D2 pl F#2 pl A2 pl C3  pl D3 pl F#3 pl A3 pl C4 delay 0 .05 .1 .15 .2 .25 remix - fade 0 1.5 .1 norm -1  ;;
-) play -n synth pl G2 pl B2 pl D2 pl G3 pl B3 pl D3 delay 0 .05 .1 .15 .2 .25 remix - fade 0 1.5 .1 norm -1  ;;
0) exit 0;;
*) echo "Oopps!!! Please select choice 1,2,3,4,5,6,7,8,9,-, or +"
echo "Press Enter to continue. . ." ; read ;;
esac
done

Note: make sure sox is installed.
$ sudo apt-get install sox
—————————————–

Made this variation on a tv antenna. A cd case with clips on the side.  Have not really tried it yet. It basically the same old antenna like the traditional coat hanger antennas, but just using different parts.

Screenshot - 01112015 - 10:24:13 PM

And the unit itself: (one connecting wire for each side.

F64PM41I4SCK1A9.MEDIUM

—————————————–

Simple fried eggs and turkey bacon.

SUNP0025

Good day.

Jan_uary.

Leave a comment

Chit chat

=======

If there is something in particular you are looking for please use the search function on the upper right hand side of the page.

Screenshot - 01092015 - 08:17:30 PM

Interesting that we were looking at an old BSD box. Started to use some of the package commands. Surprised it had nano and not vim. After setting the package path, we were also able to add vim easily. Unfortunately, the install is several versions behind. Since nothing was ever really installed on the machine, it might be easier to reinstall from scratch. Shut the system down for the moment.

Plugged in another drive into that same system and found Tinycore linux including gui installed on it  Amazing it runs with only a P1 and a legacy isa not “pci vga card. You sure could not do that with the latest version of the commercial operating systems. Did a tce-update and kept on rolling.

Had another old motherboard go south. With the bulging capacitors. Shame though it worked well in an atx case. Probably will not take the time to repair it. Will scavenge parts like the battery holder and et cetera for electronics projects.


Was experimenting what to do with some old Realtek network interface cards (aka nics) that there was a patch available for allowing them to be pxebootable.

ls:

$ ls
1 2 3 4 5
$ ls -l
total 0
-rw-rw-r– 1 eddie eddie 0 Jan 10 05:13 1
-rw-rw-r– 1 eddie eddie 0 Jan 10 05:13 2
-rw-rw-r– 1 eddie eddie 0 Jan 10 05:13 3
-rw-rw-r– 1 eddie eddie 0 Jan 10 05:13 4
-rw-rw-r– 1 eddie eddie 0 Jan 10 05:13 5
x$ ls -rl
total 0
-rw-rw-r– 1 eddie eddie 0 Jan 10 05:13 5
-rw-rw-r– 1 eddie eddie 0 Jan 10 05:13 4
-rw-rw-r– 1 eddie eddie 0 Jan 10 05:13 3
-rw-rw-r– 1 eddie eddie 0 Jan 10 05:13 2
-rw-rw-r– 1 eddie eddie 0 Jan 10 05:13 1
$ ls -rt
1 2 3 4 5
$ ls -t
5 4 3 2 1

Watch nic input:

$ watch -n1 “ifconfig eth0 | grep ‘RX'”

Screenshot - 01112015 - 03:42:51 PM

Installed freebasic on the old P1 with Slackware. Copied a couple of files over and they seemed to compile and run okay.

Had to change the nic on the Slackware setup, Wanted to use a cheaper card.  Found some docs on the net and fixed it quickly. Updated the router for the  mac change of the IPaddress reservation.

—————————————

Text clocks seem to be a big thing right now. Here is one written in qbasic.

qb64 result:

Freebasic result;

Source code:

'UNSEEN'S NOT A STANDARD CLOCK
DIM SEC AS STRING, MIN AS STRING, HR AS STRING
SCREEN 0: COLOR 3, 15: WIDTH 40, 25
CLS
DO
HR$ = LEFT$(TIME$, 2): MIN$ = MID$(TIME$, 4, 2): SEC$ = RIGHT$(TIME$, 2)
LOCATE 1, 1: PRINT HR$; ":"; MIN$; ":"; SEC$
'MINUTES
IF (VAL(MIN$) <  10 and val(min$) >= 5) OR (VAL(MIN$) >= 55 AND VAL(MIN$) < 60) THEN COLOR 12, 15
LOCATE 3, 2: PRINT "FIVE": COLOR 3, 15
IF VAL(MIN$) >= 10 AND VAL(MIN$) < 15 OR VAL(MIN$) >= 50 AND VAL(MIN$) < 55 THEN COLOR 12, 15
LOCATE 3, 8: PRINT "TEN": COLOR 3, 15
IF VAL(MIN$) >= 15 AND VAL(MIN$) < 20 OR VAL(MIN$) >= 45 AND VAL(MIN$) < 50 THEN COLOR 12, 15
LOCATE 3, 13: PRINT "FIFTEEN": COLOR 3, 15
IF VAL(MIN$) >= 20 AND VAL(MIN$) < 25 OR VAL(MIN$) >= 40 AND VAL(MIN$) < 45 THEN COLOR 12, 15
LOCATE 3, 21: PRINT "TWENTY": COLOR 3, 15
IF VAL(MIN$) >= 25 AND VAL(MIN$) < 30 OR VAL(MIN$) >= 35 AND VAL(MIN$) < 40 THEN COLOR 12, 15
LOCATE 3, 28: PRINT "TWENTY FIVE": COLOR 3, 15
LOCATE 7, 12: PRINT "MIN'S"
'EXTRA MINUTES
IF VAL(MIN$) > 30 THEN COLOR 12, 15
LOCATE 5, 3: PRINT "MINUS": COLOR 3, 15
IF VAL(MIN$) < 30 THEN COLOR 12, 15
LOCATE 5, 10: PRINT "PLUS": COLOR 3, 15
IF VAL(MID$(TIME$, 5, 1)) = 6 OR VAL(MID$(TIME$, 5, 1)) = 4 THEN COLOR 12, 15
LOCATE 7, 3: PRINT "1": COLOR 3, 15
IF VAL(MID$(TIME$, 5, 1)) = 7 OR VAL(MID$(TIME$, 5, 1)) = 3 THEN COLOR 12, 15
LOCATE 7, 5: PRINT "2": COLOR 3, 15
IF VAL(MID$(TIME$, 5, 1)) = 8 OR VAL(MID$(TIME$, 5, 1)) = 2 THEN COLOR 12, 15
LOCATE 7, 7: PRINT "3": COLOR 3, 15
IF VAL(MID$(TIME$, 5, 1)) = 9 OR VAL(MID$(TIME$, 5, 1)) = 1 THEN COLOR 12, 15
LOCATE 7, 9: PRINT "4": COLOR 3, 15
'TO PAST
IF VAL(MIN$) > 30 THEN COLOR 12, 15
LOCATE 9, 10: PRINT "TO THE NEXT HOUR": COLOR 3, 15
IF VAL(MIN$) <= 30 THEN COLOR 12, 15
LOCATE 9, 30: PRINT "PAST": : COLOR 3, 15
IF VAL(MIN$) = 30 THEN COLOR 12, 15
LOCATE 9, 36: PRINT "HALF ": COLOR 3, 15
'HOURS
IF VAL(HR$) = 1 OR VAL(HR$) = 13 THEN COLOR 12, 15
LOCATE 11, 2: PRINT "ONE": COLOR 3, 15
IF VAL(HR$) = 2 OR VAL(HR$) = 14 THEN COLOR 12, 15
LOCATE 11, 7: PRINT "TWO": COLOR 3, 15
IF VAL(HR$) = 3 OR VAL(HR$) = 15 THEN COLOR 12, 15
LOCATE 11, 12: PRINT "THREE": COLOR 3, 15
IF VAL(HR$) = 4 OR VAL(HR$) = 16 THEN COLOR 12, 15
LOCATE 11, 19: PRINT "FOUR": COLOR 3, 15
IF VAL(HR$) = 5 OR VAL(HR$) = 17 THEN COLOR 12, 15
LOCATE 11, 25: PRINT "FIVE": COLOR 3, 15
IF VAL(HR$) = 6 OR VAL(HR$) = 18 THEN COLOR 12, 15
LOCATE 11, 30: PRINT "SIX": COLOR 3, 15
IF VAL(HR$) = 7 OR VAL(HR$) = 19 THEN COLOR 12, 15
LOCATE 11, 35: PRINT "SEVEN": COLOR 3, 15
IF VAL(HR$) = 8 OR VAL(HR$) = 20 THEN COLOR 12, 15
LOCATE 12, 5: PRINT "EIGHT": COLOR 3, 15
IF VAL(HR$) = 9 OR VAL(HR$) = 21 THEN COLOR 12, 15
LOCATE 12, 12: PRINT "NINE": COLOR 3, 15
IF VAL(HR$) = 10 OR VAL(HR$) = 22 THEN COLOR 12, 15
LOCATE 12, 18: PRINT "TEN": COLOR 3, 15
IF VAL(HR$) = 11 OR VAL(HR$) = 23 THEN COLOR 12, 15
LOCATE 12, 23: PRINT "ELEVEN": COLOR 3, 15
IF VAL(HR$) = 0 OR VAL(HR$) = 12 THEN COLOR 12, 15
LOCATE 12, 31: PRINT "TWELVE": COLOR 3, 15
'AM-PM
IF VAL(HR$) >= 12 THEN COLOR 12, 15
LOCATE 16, 5: PRINT "PM": COLOR 3, 15
IF VAL(HR$) < 12 THEN COLOR 12, 15
LOCATE 16, 2: PRINT "AM": COLOR 3, 15
'SECONDS
COLOR 12, 15: LOCATE 19, 2: PRINT "AND"
COLOR 3, 15
IF VAL(SEC$) = 5 THEN COLOR 12, 15
LOCATE 21, 1: PRINT "5": COLOR 3, 15
IF VAL(SEC$) = 10 THEN COLOR 12, 15
LOCATE 21, 3: PRINT "10": COLOR 3, 15
IF VAL(SEC$) = 15 THEN COLOR 12, 15
LOCATE 21, 7: PRINT "15": COLOR 3, 15
IF VAL(SEC$) = 20 THEN COLOR 12, 15
LOCATE 21, 11: PRINT "20": COLOR 3, 15
IF VAL(SEC$) = 25 THEN COLOR 12, 15
LOCATE 21, 15: PRINT "25": COLOR 3, 15
IF VAL(SEC$) = 30 THEN COLOR 12, 15
LOCATE 21, 19: PRINT "30": COLOR 3, 15
IF VAL(SEC$) = 35 THEN COLOR 12, 15
LOCATE 21, 23: PRINT "35": COLOR 3, 15
IF VAL(SEC$) = 40 THEN COLOR 12, 15
LOCATE 21, 27: PRINT "40": COLOR 3, 15
IF VAL(SEC$) = 45 THEN COLOR 12, 15
LOCATE 21, 31: PRINT "45": COLOR 3, 15
IF VAL(SEC$) = 50 THEN COLOR 12, 15
LOCATE 21, 35: PRINT "50": COLOR 3, 15
IF VAL(SEC$) = 55 THEN COLOR 12, 15
LOCATE 21, 39: PRINT "55": COLOR 3, 15
COLOR 12, 15: LOCATE 23, 32: PRINT "SECONDS"
COLOR 3, 15
LOOP

—————————————

The Chumby makes a great Musak type device. You will need a program like gnump3d on a server with some audio files.

FVIYRO9I4IDCEC4.LARGE

You can use a program on linux called fapg to create an m3u playlist.Our connection from the Chumby to the server is:

FTB1702I4IDD8C1.LARGE

Server Name: Typo1

URL: http://typo1:8888:/stream.m3u

typo1:/var/media/music

Note: music server directory is set to /var/media/music
typo1:/var/media/music$ ls
bsd contemporary stream.m3u clientplaylist_192.168.1.122.m3u folk and classical

—————————————

Simple mandlebrot prog compile in freebasic.


Screenshot from 2015-01-06 14:51:29

SCREEN 13
WINDOW (-2, 1.5)-(2, -1.5)
FOR x0 = -2 TO 2 STEP .01
FOR y0 = -1.5 TO 1.5 STEP .01
x = 0
y = 0
iteration = 0
maxIteration = 223
WHILE (x * x + y * y <= (2 * 2) AND iteration < maxIteration)
xtemp = x * x - y * y + x0
y = 2 * x * y + y0
x = xtemp
iteration = iteration + 1
WEND
IF iteration <> maxIteration THEN
c = iteration
ELSE
c = 0
END IF
PSET (x0, y0), c + 32
NEXT
NEXT
Input"press enter to quit",a

Qb64 version:

Screenshot from 2015-01-06 14:51:29

—————————————

Screenshot - 01092015 - 10:03:30 PM

One thing that you home router provides is internet protocol addresses to every machine on the network with out you having to manually assign the ipaddresses (aka computer telephone numbers) to all the systems that request an address. It also associates hostnames for system connected to it like a telephone book.  If for some reason your router fails, you can use an existing system to replace those services. You just need to install a software package known as Dnsmasq. In fact. that is the exact software most routers use to be a localize domain name services. You will want to use an extra nic so that later you can turn the system into a router.

From the Debian wiki.

Dnsmasq is a lightweight, easy to configure, DNS forwarder and DHCP server. It is designed to provide DNS and optionally, DHCP, to a small network. It can serve the names of local machines which are not in the global DNS. The DHCP server integrates with the DNS server and allows machines with DHCP-allocated addresses to appear in the DNS with names configured either in each host or in a central configuration file. Dnsmasq supports static and dynamic DHCP leases and BOOTP/TFTP for network booting of diskless machines (source: from the package description).

Basic DNS setup

First things first, let’s install the package:

apt-get update
apt-get install dnsmasq

If your goal was to set up a simple DNS server, you just succeeded. To test it, use your favorite DNS lookup tool pointed at localhost:

dig debian.org @localhost

or

nslookup debian.org localhost

By default, DNS is configured to forward all requests to your system’s default DNS settings. In case you didn’t know, these are stored in the /etc/resolv.conf file. See Debian Reference or the resolv.conf(5) man page for more details.

Now, if you want to add some names for your DNS server to resolve for your clients, simply add them to your /etc/hosts file.

Interfaces

One thing you will probably want to do is tell dnsmasq which ethernet interface it can and cannot listen on, as we really don’t want it listening on the internet. Around line 69 of the /etc/dnsmasq.conf file, you will see:

#interface=

Uncomment the line and specify which ethernet interface(s) you want it server IPs to. For example, if I want it to listen on eth1 (my DMZ) and eth2 (my local network), then it should look like:

interface=eth1
interface=eth2

If I didn’t edit this line, it would also listen on eth0, my internet connection. I personally wouldn’t recommend this, as it gives those evil guys a few doors to try to break into.

Basic dhcp setup

By default, DHCP is turned off. This is a good thing, as you could bring down whatever network you are connected to if you are not careful.

To enable it, there is at least one line will need to edit in the /etc/dnsmasq.conf file. Around line 143, you will see: Make sure the existing network you are plugging into is not 192.168.0.x

#dhcp-range=192.168.0.50,192.168.0.150,12h

To enable the DHCP server, you will need to give it a range of IP addresses to hand out. In the example above, this server would hand out 101 address starting at 192.168.0.50 and ending at 192.168.0.150. The last number is how long the DHCP leases are good for. In this example, they would be good for twelve hours.

(Assuming he is using three nics and you are not using an existing device using dnsmasq) Since I have two different networks that need DHCP, I’m going to change that line to:

dhcp-range=eth1,192.168.100.100,192.168.100.199,4h
dhcp-range=eth2,192.168.200.100,192.168.200.199,4h

Notice the “eth1″ and “eth2″ labels in the lines above? The aren’t necessary, but definately help once you start playing with more advanced configurations. It also helps me remember which range is which. Now restart your dnsmasq server, connect up a few clients, and see if they autoconfigure themselves:

/etc/init.d/dnsmasq restart

Local caching

Using dnsmasq to cache DNS queries for the local machine is a bit tricky, since all DNS queries from the local machine need to go to dnsmasq, while as the same time, dnsmasq must be configured to forward all those queries to upstream DNS servers.

  • <!> Do not use this configuration if you use different network (e.g If you use a laptop!)

The dnsmasq(8) man page suggests the following:

  • In order to configure dnsmasq to act as cache for the host on which it is running, put “nameserver 127.0.0.1″ in /etc/resolv.conf to force local processes to send queries to dnsmasq. Then either specify the upstream servers directly to dnsmasq using –server options or put their addresses real in another file, say /etc/resolv.dnsmasq and run dnsmasq with the -r /etc/resolv.dnsmasq option. This second technique allows for dynamic update of the server addresses by PPP or DHCP.

There is, however, a simpler method; simply ensure that the machine’s list of nameservers contains the line

nameserver 127.0.0.1

as the first line, followed by the upstream nameservers. dnsmasq is smart enough to ignore this line and forward all queries appropriately, while all other applications will send all their queries to dnsmasq.

Exaclty how to do this depends on the method(s) of network configuration in use. If you’re manually hardcoding the nameservers (either in /etc/resolv.conf or elsewhere, such as a stanza in /etc/network/interfaces or in the Wicd GUI), then just add a reference to 127.0.0.1 as the first entry in the list. If you’re using DHCP, then instruct your client to prepend 127.0.0.1 to the DHCP servers it receives. E.g., with dhclient, include the line

prepend domain-name-servers 127.0.0.1;

in the dhclient configuration file (/etc/dhcp3/dhclient.conf). [On my Sid system, the default configuration file shipped with the package contains that line, but commented out.]

Note that if you plan to use dnsmasq for the local system only, you should lock it down by adding the line (not used on out dnsmasq setup when I looked at the file.)

listen-address=127.0.0.1

to the dnsmasq configuration file (/etc/dnsmasq.conf).

—————————————

Screenshot - 01102015 - 12:07:53 AM

Debian gateway/router.

A multitude of reasons exist as to why one would want to build a custom router vs. suffer with the performance, reliability issues, and limitations of an off-the-shelf solution.  What we are about to do is configure an incredibly fast and stable router/gateway solution for your home/office in about 15 minutes. (Note: This post assumes you already have your machine loaded up with a fresh copy of Debian and you have the two needed NICs installed. With systemd on the horizon, this setup will change. I would probably use auto instead of hotplug to configure the interfaces.

First, let’s make three initial assumptions:

  • eth0 is the public interface (the Cable/DSL modem is attached to this NIC)
  • eth1 is the private interface (your switch is connected to this NIC)
  • All of the client computers, servers, WAPs, etc. are connected to the switch

Let’s get started with the configuration. Set your timer and type quickly! :)

1.) Configure the network interfaces
Change the “address”, “netmask”, and “broadcast” values to match your internal network preferences.

nano -w /etc/network/interfaces
# The external WAN interface (eth0)
# auto eth0
allow-hotplug eth0
iface eth0 inet dhcp

# The internal LAN interface (eth1)
# auto eth1
allow-hotplug eth1
iface eth1 inet static
   address 192.168.0.1
   netmask 255.255.255.0
   network 192.168.0.0
   broadcast 192.168.0.255

2. Install and configure DNSmasq
DNSmasq is DNS forwarder and DHCP server. Change “domain” to the FQDN of your network and “dhcp-range” to the desired range of DHCP addresses you would like your router to serve out to clients.

apt-get install dnsmasq
nano -w /etc/dnsmasq.conf
interface=eth1
#not used this feature, but it might be a good idea to.
listen-address=127.0.0.1
domain=home.andreimatei.com
dhcp-range=192.168.0.100,192.168.0.110,12h

3.) Enable IP Forwarding
Uncomment the following line:

nano -w /etc/sysctl.conf
net.ipv4.ip_forward=1

4.) Configure iptables
We create a file called /etc/iptables.rules and put this rule set inside of it.  As an example, this set includes allowing tcp traffic in from the outside world on port 222 (I run SSH on this alternate port) and also port-forwards tcp port 50,000 to an internal machine with the ip of 192.168.0.3.  Use this as a guide for your own rules. This known as a firewall script. Use this or any other script at your own risk.

nano -w /etc/iptables.rules
*nat
-A PREROUTING -i eth0 -p tcp -m tcp --dport 50000 -j DNAT --to-destination 192.168.0.3:50000
-A POSTROUTING -o eth0 -j MASQUERADE
COMMIT

*filter
-A INPUT -i lo -j ACCEPT
-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
-A INPUT -i eth0 -p tcp -m tcp --dport 222 -j ACCEPT
-A INPUT -i eth0 -j DROP
-A FORWARD -i eth0 -p tcp -m tcp --dport 50000 -m state --state NEW -j ACCEPT
COMMIT

5.) Activate your iptables rules

iptables-restore < /etc/iptables.rules

6.) Ensure iptables rules start on boot
Insert the following line into your /etc/network/interfaces file right underneath “iface lo inet loopback”

nano -w /etc/network/interfaces
pre-up iptables-restore < /etc/iptables.rules

7.) Reboot and Verify
That’s it! After a reboot, you should now have a very basic Linux Router/Gateway for your network.

This post obviously doesn’t cover some of the incredible additional flexibility which your new machine provides.  I urge you to explore topics on traffic shaping, throughput monitoring, Intrusion Detection, and VPN configuration to learn how to harness the true power of running a dedicated machine as the central traffic cop of your network.

Other firewall scripts:

# if you don't have wget on your system, install it (on debian apt-get install wget)
wget http://robert.penz.name/files/firewall/iptables_firewall_scripts-0.3.tar.bz2

tar xjf iptables_firewall_scripts-0.3.tar.bz2
# if you get an error message you don't have the bzip2 installed --> install it
# (on debian apt-get install bzip2)

Also see:

https://help.ubuntu.com/community/IptablesHowTo

http://www.perkin.org.uk/posts/iptables-script-for-debian-ubuntu.html

https://wiki.debian.org/Firewalls

https://wiki.debian.org/iptables

Robert Penz Blog Logo Robert Penz Blog URL

—————————————

Code location: https://github.com/skilldrick/6502js

Introduction

In this tiny ebook I’m going to show you how to get started writing 6502 assembly language. The 6502 processor was massive in the seventies and eighties, powering famous computers like the BBC Micro, Atari 2600, Commodore 64, Apple II, and the Nintendo Entertainment System. Bender in Futurama has a 6502 processor for a brain. Even the Terminator was programmed in 6502.

So, why would you want to learn 6502? It’s a dead language isn’t it? Well, so’s Latin. And they still teach that. Q.E.D.  (Actually, I’ve been reliably informed that 6502 processors are still being produced by Western Design Center, so clearly 6502 isn’t a dead language! Who knew?)

Seriously though, I think it’s valuable to have an understanding of assembly language. Assembly language is the lowest level of abstraction in computers – the point at which the code is still readable. Assembly language translates directly to the bytes that are executed by your computer’s processor. If you understand how it works, you’ve basically become a computer magician.

Then why 6502? Why not a useful assembly language, like x86? Well, I don’t think learning x86 is useful. I don’t think you’ll ever have to write assembly language in your day job – this is purely an academic exercise, something to expand your mind and your thinking. 6502 was originally written in a different age, a time when the majority of developers were writing assembly directly, rather than in these new-fangled high-level programming languages. So, it was designed to be written by humans. More modern assembly languages are meant to written by compilers, so let’s leave it to them. Plus, 6502 is fun. Nobody ever called x86 fun.

Our first program

So, let’s dive in! That thing below is a little JavaScript 6502 assembler and simulator that I adapted for this book. Click Assemble then Run to assemble and run the snippet of assembly language.

LDA #$01
STA $0200
LDA #$05
STA $0201
LDA #$08
STA $0202

Debugger

Monitor Start: $ Length: $

Hopefully the black area on the right now has three coloured “pixels” at the top left. (If this doesn’t work, you’ll probably need to upgrade your browser to something more modern, like Chrome or Firefox.)
So, what’s this program actually doing? Let’s step through it with the debugger. Hit Reset, then check the Debugger checkbox to start the debugger. Click Step once. If you were watching carefully, you’ll have noticed that A= changed from $00 to $01, and PC= changed from $0600 to $0602.

Any numbers prefixed with $ in 6502 assembly language (and by extension, in this book) are in hexadecimal (hex) format. If you’re not familiar with hex numbers, I recommend you read the Wikipedia article. Anything prefixed with # is a literal number value. Any other number refers to a memory location.
Equipped with that knowledge, you should be able to see that the instruction LDA #$01 loads the hex value $01 into register A. I’ll go into more detail on registers in the next section.

Press Step again to execute the second instruction. The top-left pixel of the simulator display should now be white. This simulator uses the memory locations $0200 to $05ff to draw pixels on its display. The values $00 to $0f represent 16 different colours ($00 is black and $01 is white), so storing the value $01 at memory location $0200 draws a white pixel at the top left corner. This is simpler than how an actual computer would output video, but it’ll do for now.

So, the instruction STA $0200 stores the value of the A register to memory location $0200. Click Step four more times to execute the rest of the instructions, keeping an eye on the A register as it changes.

Exercises

  1. Try changing the colour of the three pixels.
  2. Change one of the pixels to draw at the bottom-right corner (memory location $05ff).
  3. Add more instructions to draw extra pixels.

Registers and flags

We’ve already had a little look at the processor status section (the bit with A, PC etc.), but what does it all mean?  The first line shows the A, X and Y registers (A is often called the “accumulator”). Each register holds a single byte. Most operations work on the contents of these registers.  

SP is the stack pointer. I won’t get into the stack yet, but basically this register is decremented every time a byte is pushed onto the stack, and incremented when a byte is popped off the stack.

PC is the program counter – it’s how the processor knows at what point in the program it currently is. It’s like the current line number of an executing script. In the JavaScript simulator the code is assembled starting at memory location $0600, so PC always starts there.

The last section shows the processor flags. Each flag is one bit, so all seven flags live in a single byte. The flags are set by the processor to give information about the previous instruction. More on that later. Read more about the registers and flags here.

Instructions

Instructions in assembly language are like a small set of predefined functions. All instructions take zero or one arguments. Here’s some annotated source code to introduce a few different instructions:

LDA #$c0 ;Load the hex value $c0 into the A register
TAX ;Transfer the value in the A register to X
INX ;Increment the value in the X register
ADC #$c4 ;Add the hex value $c4 to the A register
BRK ;Break – we’re done

Debugger

Monitor Start: $ Length: $

Assemble the code, then turn on the debugger and step through the code, watching the A and X registers. Something slightly odd happens on the line ADC #$c4. You might expect that adding $c4 to $c0 would give $184, but this processor gives the result as $84. What’s up with that?

The problem is, $184 is too big to fit in a single byte (the max is $FF), and the registers can only hold a single byte. It’s OK though; the processor isn’t actually dumb. If you were looking carefully enough, you’ll have noticed that the carry flag was set to 1 after this operation. So that’s how you know.
In the simulator below type (don’t paste) the following code:

LDA #$80
STA $01
ADC $01

Debugger

Monitor Start: $ Length: $

An important thing to notice here is the distinction between ADC #$01 and ADC $01. The first one adds the value $01 to the A register, but the second adds the value stored at memory location $01 to the A register.

Assemble, check the Monitor checkbox, then step through these three instructions. The monitor shows a section of memory, and can be helpful to visualise the execution of programs. STA $01 stores the value of the A register at memory location $01, and ADC $01 adds the value stored at the memory location $01 to the A register. $80 + $80 should equal $100, but because this is bigger than a byte, the A register is set to $00 and the carry flag is set. As well as this though, the zero flag is set. The zero flag is set by all instructions where the result is zero.

A full list of the 6502 instruction set is available here and here (I usually refer to both pages as they have their strengths and weaknesses). These pages detail the arguments to each instruction, which registers they use, and which flags they set. They are your bible.

Exercises

  1. You’ve seen TAX. You can probably guess what TAY, TXA and TYA do, but write some code to test your assumptions.
  2. Rewrite the first example in this section to use the Y register instead of the X register.
  3. The opposite of ADC is SBC (subtract with carry). Write a program that uses this instruction.

Branching

So far we’re only able to write basic programs without any branching logic. Let’s change that.
6502 assembly language has a bunch of branching instructions, all of which branch based on whether certain flags are set or not. In this example we’ll be looking at BNE: “Branch on not equal”.

LDX #$08
decrement:
DEX
STX $0200
CPX #$03
BNE decrement
STX $0201
BRK

Debugger

Monitor Start: $ Length: $

First we load the value $08 into the X register. The next line is a label. Labels just mark certain points in a program so we can return to them later. After the label we decrement X, store it to $0200 (the top-left pixel), and then compare it to the value $03. CPX compares the value in the X register with another value. If the two values are equal, the Z flag is set to 1, otherwise it is set to 0.

The next line, BNE decrement, will shift execution to the decrement label if the Z flag is set to 0 (meaning that the two values in the CPX comparison were not equal), otherwise it does nothing and we store X to $0201, then finish the program.
In assembly language, you’ll usually use labels with branch instructions. When assembled though, this label is converted to a single-byte relative offset (a number of bytes to go backwards or forwards from the next instruction) so branch instructions can only go forward and back around 256 bytes. This means they can only be used to move around local code. For moving further you’ll need to use the jumping instructions.

Exercises

  1. The opposite of BNE is BEQ. Try writing a program that uses BEQ.
  2. BCC and BCS (“branch on carry clear” and “branch on carry set”) are used to branch on the carry flag. Write a program that uses one of these two.

Addressing modes

The 6502 uses a 16-bit address bus, meaning that there are 65536 bytes of memory available to the processor. Remember that a byte is represented by two hex characters, so the memory locations are generally represented as $0000 - $ffff. There are various ways to refer to these memory locations, as detailed below.

With all these examples you might find it helpful to use the memory monitor to watch the memory change. The monitor takes a starting memory location and a number of bytes to display from that location. Both of these are hex values. For example, to display 16 bytes of memory from $c000, enter c000 and 10 into Start and Length, respectively.

Absolute: $c000

With absolute addressing, the full memory location is used as the argument to the instruction. For example:

 
STA $c000 ;Store the value in the accumulator at memory location $c000

Zero page: $c0

All instructions that support absolute addressing (with the exception of the jump instructions) also have the option to take a single-byte address. This type of addressing is called “zero page” – only the first page (the first 256 bytes) of memory is accessible. This is faster, as only one byte needs to be looked up, and takes up less space in the assembled code as well.

Zero page,X: $c0,X

This is where addressing gets interesting. In this mode, a zero page address is given, and then the value of the X register is added. Here is an example:

LDX #$01   ;X is $01
LDA #$aa   ;A is $aa
STA $a0,X ;Store the value of A at memory location $a1
INX        ;Increment X
STA $a0,X ;Store the value of A at memory location $a2

If the result of the addition is larger than a single byte, the address wraps around. For example:

LDX #$05
STA $ff,X ;Store the value of A at memory location $04

Zero page,Y: $c0,Y

This is the equivalent of zero page,X, but can only be used with LDX and STX.

Absolute,X and absolute,Y: $c000,X and $c000,Y

These are the absolute addressing versions of zero page,X and zero page,Y. For example:

LDX #$01
STA $0200,X ;Store the value of A at memory location $0201

Immediate: #$c0

Immediate addressing doesn’t strictly deal with memory addresses – this is the mode where actual values are used. For example, LDX #$01 loads the value $01 into the X register. This is very different to the zero page instruction LDX $01 which loads the value at memory location $01 into the X register.

Relative: $c0 (or label)

Relative addressing is used for branching instructions. These instructions take a single byte, which is used as an offset from the following instruction.
Assemble the following code, then click the Hexdump button to see the assembled code.

LDA #$01
CMP #$02
BNE notequal
STA $22
notequal:
BRK

Debugger

Monitor Start: $ Length: $

The hex should look something like this:

 
a9 01 c9 02 d0 02 85 22 00

a9 and c9 are the processor opcodes for immediate-addressed LDA and CMP respectively. 01 and 02 are the arguments to these instructions. d0 is the opcode for BNE, and its argument is 02. This means “skip over the next two bytes” (85 22, the assembled version of STA $22). Try editing the code so STA takes a two-byte absolute address rather than a single-byte zero page address (e.g. change STA $22 to STA $2222). Reassemble the code and look at the hexdump again – the argument to BNE should now be 03, because the instruction the processor is skipping past is now three bytes long.

Implicit

Some instructions don’t deal with memory locations (e.g. INX – increment the X register). These are said to have implicit addressing – the argument is implied by the instruction.

Indirect: ($c000)

Indirect addressing uses an absolute address to look up another address. The first address gives the least significant byte of the address, and the following byte gives the most significant byte. That can be hard to wrap your head around, so here’s an example:

LDA #$01
STA $f0
LDA #$cc
STA $f1
JMP ($00f0) ;dereferences to $cc01

Debugger

Monitor Start: $ Length: $

In this example, $f0 contains the value $01 and $f1 contains the value $cc. The instruction JMP ($f0) causes the processor to look up the two bytes at $f0 and $f1 ($01 and $cc) and put them together to form the address $cc01, which becomes the new program counter. Assemble and step through the program above to see what happens. I’ll talk more about JMP in the section on Jumping.

Indexed indirect: ($c0,X)

This one’s kinda weird. It’s like a cross between zero page,X and indirect. Basically, you take the zero page address, add the value of the X register to it, then use that to look up a two-byte address. For example:

LDX #$01
LDA #$05
STA $01
LDA #$06
STA $02
LDY #$0a
STY $0605
LDA ($00,X)

Debugger

Monitor Start: $ Length: $

Memory locations $01 and $02 contain the values $05 and $06 respectively. Think of ($00,X) as ($00 + X). In this case X is $01, so this simplifies to ($01). From here things proceed like standard indirect addressing – the two bytes at $01 and $02 ($05 and $06) are looked up to form the address $0605. This is the address that the Y register was stored into in the previous instruction, so the A register gets the same value as Y, albeit through a much more circuitous route. You won’t see this much.

Indirect indexed: ($c0),Y

Indirect indexed is like indexed indirect but less insane. Instead of adding the X register to the address before dereferencing, the zero page address is dereferenced, and the Y register is added to the resulting address.

LDY #$01
LDA #$03
STA $01
LDA #$07
STA $02
LDX #$0a
STX $0704
LDA ($01),Y

Debugger

Monitor Start: $ Length: $

In this case, ($01) looks up the two bytes at $01 and $02: $03 and $07. These form the address $0703. The value of the Y register is added to this address to give the final address $0704.

Exercise

  1. Try to write code snippets that use each of the 6502 addressing modes. Remember, you can use the monitor to watch a section of memory.

The stack

The stack in a 6502 processor is just like any other stack – values are pushed onto it and popped (“pulled” in 6502 parlance) off it. The current depth of the stack is measured by the stack pointer, a special register. The stack lives in memory between $0100 and $01ff. The stack pointer is initially $ff, which points to memory location $01ff. When a byte is pushed onto the stack, the stack pointer becomes $fe, or memory location $01fe, and so on.
Two of the stack instructions are PHA and PLA, “push accumulator” and “pull accumulator”. Below is an example of these two in action.

LDX #$00
LDY #$00
firstloop:
TXA
STA $0200,Y
PHA
INX
INY
CPY #$10
BNE firstloop ;loop until Y is $10
secondloop:
PLA
STA $0200,Y
INY
CPY #$20 ;loop until Y is $20
BNE secondloop

Debugger

Monitor Start: $ Length: $

X holds the pixel colour, and Y holds the position of the current pixel. The first loop draws the current colour as a pixel (via the A register), pushes the colour to the stack, then increments the colour and position. The second loop pops the stack, draws the popped colour as a pixel, then increments the position. As should be expected, this creates a mirrored pattern.

Jumping

Jumping is like branching with two main differences. First, jumps are not conditionally executed, and second, they take a two-byte absolute address. For small programs, this second detail isn’t very important, as you’ll mostly be using labels, and the assembler works out the correct memory location from the label. For larger programs though, jumping is the only way to move from one section of the code to another.

JMP

JMP is an unconditional jump. Here’s a really simple example to show it in action:

LDA #$03
JMP there
BRK
BRK
BRK
there:
STA $0200

Debugger

Monitor Start: $ Length: $

JSR/RTS

JSR and RTS (“jump to subroutine” and “return from subroutine”) are a dynamic duo that you’ll usually see used together. JSR is used to jump from the current location to another part of the code. RTS returns to the previous position. This is basically like calling a function and returning.  The processor knows where to return to because JSR pushes the address minus one of the next instruction onto the stack before jumping to the given location. RTS pops this location, adds one to it, and jumps to that location. An example:

JSR init
JSR loop
JSR end

init:
LDX #$00
RTS

loop:
INX
CPX #$05
BNE loop
RTS

end:
BRK

Debugger

Monitor Start: $ Length: $

The first instruction causes execution to jump to the init label. This sets X, then returns to the next instruction, JSR loop. This jumps to the loop label, which increments X until it is equal to $05. After that we return to the next instruction, JSR end, which jumps to the end of the file. This illustrates how JSR and RTS can be used together to create modular code.

Creating a game

Now, let’s put all this knowledge to good use, and make a game! We’re going to be making a really simple version of the classic game ‘Snake’.
The simulator widget below contains the entire source code of the game. I’ll explain how it works in the following sections.
Willem van der Jagt made a fully annotated gist of this source code, so follow along with that for more details.

; ___ _ __ ___ __ ___
; / __|_ _ __ _| |_____ / /| __|/ \_ )
; \__ \ ‘ \/ _` | / / -_) _ \__ \ () / /
; |___/_||_\__,_|_\_\___\___/___/\__/___|

; Change direction: W A S D

; $00-01 => screen location of apple
; $10-11 => screen location of snake head
; $12-?? => snake body (in byte pairs)
; $02 => direction (1 => up, 2 => right, 4 => down, 8 => left)
; $03 => snake length

jsr init
jsr loop

init:
jsr initSnake
jsr generateApplePosition
rts

initSnake:
lda #2 ;start direction
sta $02
lda #4 ;start length
sta $03
lda #$11
sta $10
lda #$10
sta $12
lda #$0f
sta $14
lda #$04
sta $11
sta $13
sta $15
rts

generateApplePosition:
;load a new random byte into $00
lda $fe
sta $00

;load a new random number from 2 to 5 into $01
lda $fe
and #$03 ;mask out lowest 2 bits
clc
adc #2
sta $01

rts

loop:
jsr readKeys
jsr checkCollision
jsr updateSnake
jsr drawApple
jsr drawSnake
jsr spinWheels
jmp loop

readKeys:
lda $ff
cmp #$77
beq upKey
cmp #$64
beq rightKey
cmp #$73
beq downKey
cmp #$61
beq leftKey
rts
upKey:
lda #4
bit $02
bne illegalMove

lda #1
sta $02
rts
rightKey:
lda #8
bit $02
bne illegalMove

lda #2
sta $02
rts
downKey:
lda #1
bit $02
bne illegalMove

lda #4
sta $02
rts
leftKey:
lda #2
bit $02
bne illegalMove

lda #8
sta $02
rts
illegalMove:
rts

checkCollision:
jsr checkAppleCollision
jsr checkSnakeCollision
rts

checkAppleCollision:
lda $00
cmp $10
bne doneCheckingAppleCollision
lda $01
cmp $11
bne doneCheckingAppleCollision

;eat apple
inc $03
inc $03 ;increase length
jsr generateApplePosition
doneCheckingAppleCollision:
rts

checkSnakeCollision:
ldx #2 ;start with second segment
snakeCollisionLoop:
lda $10,x
cmp $10
bne continueCollisionLoop

maybeCollided:
lda $11,x
cmp $11
beq didCollide

continueCollisionLoop:
inx
inx
cpx $03 ;got to last section with no collision
beq didntCollide
jmp snakeCollisionLoop

didCollide:
jmp gameOver
didntCollide:
rts

updateSnake:
ldx $03 ;location of length
dex
txa
updateloop:
lda $10,x
sta $12,x
dex
bpl updateloop

lda $02
lsr
bcs up
lsr
bcs right
lsr
bcs down
lsr
bcs left
up:
lda $10
sec
sbc #$20
sta $10
bcc upup
rts
upup:
dec $11
lda #$1
cmp $11
beq collision
rts
right:
inc $10
lda #$1f
bit $10
beq collision
rts
down:
lda $10
clc
adc #$20
sta $10
bcs downdown
rts
downdown:
inc $11
lda #$6
cmp $11
beq collision
rts
left:
dec $10
lda $10
and #$1f
cmp #$1f
beq collision
rts
collision:
jmp gameOver

drawApple:
ldy #0
lda $fe
sta ($00),y
rts

drawSnake:
ldx #0
lda #1
sta ($10,x)
ldx $03
lda #0
sta ($10,x)
rts

spinWheels:
ldx #0
spinloop:
nop
nop
dex
bne spinloop
rts

gameOver:

Debugger

Monitor Start: $ Length: $

Overall structure

After the initial block of comments (lines starting with semicolons), the first two lines are:

jsr init
jsr loop
 

init and loop are both subroutines. init initializes the game state, and loop is the main game loop. The loop subroutine itself just calls a number of subroutines sequentially, before looping back on itself:

loop:
  jsr readkeys
  jsr checkCollision
  jsr updateSnake
  jsr drawApple
  jsr drawSnake
  jsr spinwheels
  jmp loop

First, readkeys checks to see if one of the direction keys (W, A, S, D) was pressed, and if so, sets the direction of the snake accordingly. Then, checkCollision checks to see if the snake collided with itself or the apple. updateSnake updates the internal representation of the snake, based on its direction. Next, the apple and snake are drawn. Finally, spinWheels makes the processor do some busy work, to stop the game from running too quickly. Think of it like a sleep command. The game keeps running until the snake collides with the wall or itself.

Zero page usage

The zero page of memory is used to store a number of game state variables, as noted in the comment block at the top of the game. Everything in $00, $01 and $10 upwards is a pair of bytes representing a two-byte memory location that will be looked up using indirect addressing. These memory locations will all be between $0200 and $05ff – the section of memory corresponding to the simulator display. For example, if $00 and $01 contained the values $01 and $02, they would be referring to the second pixel of the display ($0201 – remember, the least significant byte comes first in indirect addressing).

The first two bytes hold the location of the apple. This is updated every time the snake eats the apple. Byte $02 contains the current direction. 1 means up, 2 right, 4 down, and 8 left. The reasoning behind these numbers will become clear later.
Finally, byte $03 contains the current length of the snake, in terms of bytes in memory (so a length of 4 means 2 pixels).

Initialization

The init subroutine defers to two subroutines, initSnake and generateApplePosition. initSnake sets the snake direction, length, and then loads the initial memory locations of the snake head and body. The byte pair at $10 contains the screen location of the head, the pair at $12 contains the location of the single body segment, and $14 contains the location of the tail (the tail is the last segment of the body and is drawn in black to keep the snake moving). This happens in the following code:

lda #$11
sta $10
lda #$10
sta $12
lda #$0f
sta $14
lda #$04
sta $11
sta $13
sta $15

This loads the value $11 into the memory location $10, the value $10 into $12, and $0f into $14. It then loads the value $04 into $11, $13 and $15. This leads to memory like this:

0010: 11 04 10 04 0f 04

which represents the indirectly-addressed memory locations $0411, $0410 and $04ff (three pixels in the middle of the display). I’m labouring this point, but it’s important to fully grok how indirect addressing works.

The next subroutine, generateApplePosition, sets the apple location to a random position on the display. First, it loads a random byte into the accumulator ($fe is a random number generator in this simulator). This is stored into $00. Next, a different random byte is loaded into the accumulator, which is then AND-ed with the value $03. This part requires a bit of a detour.

The hex value $03 is represented in binary as 00000111. The AND opcode performs a bitwise AND of the argument with the accumulator. For example, if the accumulator contains the binary value 01010101, then the result of AND with 00000111 will be 00000101.

The effect of this is to mask out the least significant three bytes of the accumulator, setting the others to zero. This converts a number in the range of 0–255 to a number in the range of 0–3.
After this, the value 2 is added to the accumulator, to create a final random number in the range 2–5.

The result of this subroutine is to load a random byte into $00, and a random number between 2 and 5 into $01. Because the least significant byte comes first with indirect addressing, this translates into a memory address between $0200 and $05ff: the exact range used to draw the display.

The game loop

Nearly all games have at their heart a game loop. All game loops have the same basic form: accept user input, update the game state, and render the game state. This loop is no different.

Reading the input

The first subroutine, readKeys, takes the job of accepting user input. The memory location $ff holds the ascii code of the most recent key press in this simulator. The value is loaded into the accumulator, then compared to $77 (the hex code for W), $64 (D), $73 (S) and $61. If any of these comparisons are successful, the program branches to the appropriate section. Each section (upKey, rightKey, etc.) first checks to see if the current direction is the opposite of the new direction. This requires another little detour.

As stated before, the four directions are represented internally by the numbers
1, 2, 4 and 8. Each of these numbers is a power of 2, thus they are represented by a binary number with a single 1:

1 => 0001 (up)
2 => 0010 (right)
4 => 0100 (down)
8 => 1000 (left)

The BIT opcode is similar to AND, but the calculation is only used to set the zero flag – the actual result is discarded. The zero flag is set only if the result of AND-ing the accumulator with argument is zero. When we’re looking at powers of two, the zero flag will only be set if the two numbers are not the same. For example, 0001 AND 0001 is not zero, but 0001 AND 0010 is zero.

So, looking at upKey, if the current direction is down (4), the bit test will be zero. BNE means “branch if the zero flag is clear”, so in this case we’ll branch to illegalMove, which just returns from the subroutine. Otherwise, the new direction (1 in this case) is stored in the appropriate memory location.

Updating the game state

The next subroutine, checkCollision, defers to checkAppleCollision and checkSnakeCollision. checkAppleCollision just checks to see if the two bytes holding the location of the apple match the two bytes holding the location of the head. If they do, the length is increased and a new apple position is generated.
checkSnakeCollision loops through the snake’s body segments, checking each byte pair against the head pair. If there is a match, then game over.

After collision detection, we update the snake’s location. This is done at a high level like so: First, move each byte pair of the body up one position in memory. Second, update the head according to the current direction. Finally, if the head is out of bounds, handle it as a collision. I’ll illustrate this with some ascii art. Each pair of brackets contains an x,y coordinate rather than a pair of bytes for simplicity.

  0    1    2    3    4
Head                 Tail
[1,5][1,4][1,3][1,2][2,2]    Starting position
[1,5][1,4][1,3][1,2][1,2]    Value of (3) is copied into (4)
[1,5][1,4][1,3][1,2][1,2]    Value of (2) is copied into (3)
[1,5][1,4][1,3][1,2][1,2]    Value of (1) is copied into (2)
[1,5][1,4][1,3][1,2][1,2]    Value of (0) is copied into (1)
[0,4][1,4][1,3][1,2][1,2]    Value of (0) is updated based on direction

At a low level, this subroutine is slightly more complex. First, the length is loaded into the X register, which is then decremented. The snippet below shows the starting memory for the snake.

 
Memory location: $10 $11 $12 $13 $14 $15

Value:           $11 $04 $10 $04 $0f $04

The length is initialized to 4, so X starts off as 3. LDA $10,x loads the value of $13 into A, then STA $12,x stores this value into $15. X is decremented, and we loop. Now X is 2, so we load $12 and store it into $14. This loops while X is positive (BPL means “branch if positive”).

Once the values have been shifted down the snake, we have to work out what to do with the head. The direction is first loaded into A. LSR means “logical shift right”, or “shift all the bits one position to the right”. The least significant bit is shifted into the carry flag, so if the accumulator is 1, after LSR it is 0, with the carry flag set.

To test whether the direction is 1, 2, 4 or 8, the code continually shifts right until the carry is set. One LSR means “up”, two means “right”, and so on.
The next bit updates the head of the snake depending on the direction. This is probably the most complicated part of the code, and it’s all reliant on how memory locations map to the screen, so let’s look at that in more detail.

You can think of the screen as four horizontal strips of 32 × 8 pixels. These strips map to $0200-$02ff, $0300-$03ff, $0400-$04ff and $0500-$05ff. The first rows of pixels are $0200-$021f, $0220-$023f, $0240-$025f, etc.

As long as you’re moving within one of these horizontal strips, things are simple. For example, to move right, just incrememnt the least significant byte (e.g. $0200 becomes $0201). To go down, add $20 (e.g. $0200 becomes $0220). Left and up are the reverse.

Going between sections is more complicated, as we have to take into account the most significant byte as well. For example, going down from $02e1 should lead to $0301. Luckily, this is fairly easy to accomplish. Adding $20 to $e1 results in $01 and sets the carry bit. If the carry bit was set, we know we also need to increment the most significant byte.

After a move in each direction, we also need to check to see if the head would become out of bounds. This is handled differently for each direction. For left and right, we can check to see if the head has effectively “wrapped around”. Going right from $021f by incrementing the least significant byte would lead to $0220, but this is actually jumping from the last pixel of the first row to the first pixel of the second row. So, every time we move right, we need to check if the new least significant byte is a multiple of $20. This is done using a bit check against the mask $1f. Hopefully the illustration below will show you how masking out the lowest 5 bits reveals whether a number is a multiple of $20 or not.

 
$20: 0010 0000
$40: 0100 0000
$60: 0110 0000
$1f: 0001 1111

I won’t explain in depth how each of the directions work, but the above explanation should give you enough to work it out with a bit of study.

Rendering the game

Because the game state is stored in terms of pixel locations, rendering the game is very straightforward. The first subroutine, drawApple, is extremely simple. It sets Y to zero, loads a random colour into the accumulator, then stores this value into ($00),y. $00 is where the location of the apple is stored, so ($00),y dereferences to this memory location. Read the “Indirect indexed” section in Addressing modes for more details.

Next comes drawSnake. This is pretty simple too. X is set to zero and A to one. We then store A at ($10,x). $10 stores the two-byte location of the head, so this draws a white pixel at the current head position. Next we load $03 into X. $03 holds the length of the snake, so ($10,x) in this case will be the location of the tail. Because A is zero now, this draws a black pixel over the tail. As only the head and the tail of the snake move, this is enough to keep the snake moving.

The last subroutine, spinWheels, is just there because the game would run too fast otherwise. All spinWheels does is count X down from zero until it hits zero again. The first dex wraps, making X #$ff.

—————————————

Rosettacode is a great place for geting code tidbits. Here is a little program we run on the nslu2 and the other embedded projects. Here is a quickie program for taking notes.

Screenshot - 01112015 - 04:55:45 PM

 PROGRAM-ID. NOTES.

 ENVIRONMENT DIVISION.
 INPUT-OUTPUT SECTION.
 FILE-CONTROL.
 SELECT OPTIONAL notes ASSIGN TO "NOTES.TXT"
 ORGANIZATION LINE SEQUENTIAL
 FILE STATUS note-status.

 DATA DIVISION.
 FILE SECTION.
 FD notes.
 01 note-record PIC X(256).

 LOCAL-STORAGE SECTION.
 01 note-status PIC 99.
 88 notes-ok VALUE 0 THRU 9.

 01 date-now.
 03 current-year PIC 9(4).
 03 current-month PIC 99.
 03 current-day PIC 99.

 01 time-now.
 03 current-hour PIC 99.
 03 current-min PIC 99.
 03 current-sec PIC 99.

 01 args PIC X(256).

 PROCEDURE DIVISION.
 DECLARATIVES.
 note-error SECTION.
 USE AFTER STANDARD ERROR PROCEDURE ON notes.

 DISPLAY "Error using NOTES.TXT. Error code: " note-status
 .
 END DECLARATIVES.

 main.
 ACCEPT args FROM COMMAND-LINE

*>  If there are no args, display contents of NOTES.TXT.
 IF args = SPACES
 OPEN INPUT notes

 PERFORM FOREVER
*> READ has no syntax highlighting, but END-READ does.
*>  Go figure.
 READ notes
 AT END
 EXIT PERFORM

 NOT AT END
 DISPLAY FUNCTION TRIM(note-record)
 END-READ
 END-PERFORM
 ELSE
 OPEN EXTEND notes

*>Write date and time to file.
 ACCEPT date-now FROM DATE YYYYMMDD
 ACCEPT time-now FROM TIME
 STRING current-year "-" current-month "-" current-day
 " " current-hour ":" current-min ":" current-sec
 INTO note-record
 WRITE note-record

*>  Write arguments to file as they were passed.
 STRING X"09", args INTO note-record
 WRITE note-record
 END-IF

 CLOSE notes

 GOBACK.

$ cobc -x -free notes.cob

—————————————

Chicken thighs. Perfect for game day.

SUNP0002

Good day.

Happy new year.

Leave a comment

Chit chat

=======

lsblk is a nice way to find out what storage devices are on your system instead of sudo fdisk -l.

$ lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
sda 8:0 0 74.5G 0 disk
├─sda1 8:1 0 71.5G 0 part /
├─sda2 8:2 0 1K 0 part
└─sda5 8:5 0 3.1G 0 part [SWAP]
sdd 8:48 1 982.5M 0 disk
└─sdd1 8:49 1 982.5M 0 part /media/eddie/disk
sr0 11:0 1 1024M 0 rom

Installed some of my old apps back on the web server such as Oscommerce and Flatpress.

More and more linux distros are beginning to drop MySQL for MariaDB.  So far they seem compatible to me. Been practising setting up lamp servers on the Raspberry Pi and old Pentium one computers.

Screenshot from 2015-01-02 02:52:15

 

SUNP0034

Amazing that you can take what some people would call a legacy machine and create a web server that does virtual hosting. (i.e. one computer and many websites).

vh

——————————————

So I have talked about booting from a web server to do an install. Now we are going to go a bit farther and boot a live image from a web server. Depending on the size of the image, your destination machine will have to have enough memory to handle the load. For our purposes, we will use a very small linux distro for testing purposes. In this case, Slitaz should fit the bill so to speak. http://www.slitaz.org/en/get/.   Like the web installs we did, you will need a pxebootable device such as a floppy, usb, or cdrom/dvdrom.

Doing a web load has been around a long time, but the average user may not be aware of it. What is really neat about this is that you have older thin clients, they would be perfect for use with the web boot for the ones that will. While I was at it, I was  able to get it to boot from tftp server to a thin client. That setup is more involved and for another day.  One shortcoming is that Slitaz does not seem to use the usb keyboard out of the box.

:/var/www/slitaz$ ls
memdisk  slitaz5.iso

If you have been following my articles, you should be aware of how to make the boot media for the ipxe boot.  Had to get to files to the web directory to boot from first is the iso of course and the second is the memdisk. If you have syslinux installed, it should be there on your system.

#!ipxe
dhcp any
initrd http://192.168.1.32/tinycore/slitaz5.iso
chain http://192.168.1.32/debianlive/memdisk iso raw

or

    kernel Kernel/memdisk (or http://192.168.10.1/Kernel/memdisk)
    append iso initrd=192.168.10.1/Images/ubcd.iso

In doing the research for this, quite a few ways to do this.

——————————————

We use the simple whiteboard like a chalk board. Surprised it even worked will being hosted on a pentium one computer running Slackware 14.1. The code is based off of the Canvas developers project. You will want to download the special programs to make the page faster to load.

$ wget https://code.jquery.com/jquery-1.11.0.min.js
$ wget https://awwapp.com/static/1.0/aww.min.js
$ wget https://awwapp.com/nowjs/now.js
$ wget https://awwapp.com/static/1.0/aww.css

You will want your web page and the files all in the same directory aka folder.

wb.hrml

<html>
<head>
<!-- jQuery 1.x is required; if you already have it included in your page,
 no need to include this -->
<script type="text/javascript" src="jquery-1.11.0.min.js"></script>

<!-- AWW widget -->
<script type="text/javascript" src="aww.min.js"></script>

<!-- Connection to the whiteboard sharing service -->
<script type="text/javascript" src="now.js"></script>

<!-- CSS styles used by the widget -->
<link rel="stylesheet" type="text/css" href="aww.css"/>

</head>
<body>
<!-- the whiteboard widget will be shown inside this element -->
<div id="wrapper" style="width: 100%; height: 600px;"></div>

<!-- this actually initializes the widget -->
<script type="text/javascript">
    $(function() {
        /* initialize the whiteboard widget on #wrapper element */
        var aww = $('#wrapper').awwCanvas();
    });
</script>
</body>
</html>

——————————————

Keeping medical records is very important. Of course, your doctor’s office will keep records, but you will want to keep your own set. Was looking at this software for doctor’s offices so they can keep records. It is so detailed, that you would enriched if you used this program yourself. The program is called openemr and is available from www.openemr.com (perfect for a doctors office). The have version for several operating systems.  The version that interested me the most was the web version, so you could install it on your own private server and everyone on the network can use it.

We setup what is known as a virtual site so that it co resides with other websites from the same server (just like the pros do it).  What is interesting os that you can keep a record of office visits. You cn even printout records for  just one visit or print the whole month out.

Of course you can add any member of the family maybe add or setup up accounts for relatives that you care about.

Of course, the financial records are important, especially at tax time.

Some people might think it is a bit overdoing it, but wait till you want to get at the information and you will really appreciate the software. Have only scratched the surface of what can be done. Check it out!

Simple mandlebrot prog compile in freebasic.

Screenshot from 2015-01-06 14:51:29


SCREEN 13
WINDOW (-2, 1.5)-(2, -1.5)
FOR x0 = -2 TO 2 STEP .01
FOR y0 = -1.5 TO 1.5 STEP .01
x = 0
y = 0
iteration = 0
maxIteration = 223
WHILE (x * x + y * y <= (2 * 2) AND iteration < maxIteration)
xtemp = x * x - y * y + x0
y = 2 * x * y + y0
x = xtemp
iteration = iteration + 1
WEND
IF iteration <> maxIteration THEN
c = iteration
ELSE
c = 0
END IF
PSET (x0, y0), c + 32
NEXT
NEXT
Input"press enter to quit",a

——————————————

FVIYRO9I4IDCEC4.LARGE

The Chumby make a great Musak type device. You will need a program like gnump3d on a server with some audio files.

You can use a program on linux called fapg to create an m3u playlist.

Our connection from the Chumby to the server is:

FTB1702I4IDD8C1.LARGE

Name: Typo1

URL: http://typo1:8888:/stream.m3u

typo1:/var/media/musi

Note: music server directory is set to /var/media/music

typo1:/var/media/music$ ls
bsd contemporary stream.m3u clientplaylist_192.168.1.122.m3u folk and classical

——————————————

Python is the rage these days so here is a simple editor in python (requires gui)

Screenshot from 2015-01-06 15:09:15


from Tkinter import *
from tkSimpleDialog import askstring
from tkFileDialog import asksaveasfilename
from tkMessageBox import askokcancel
class Quitter(Frame):
def __init__(self, parent=None):
Frame.__init__(self, parent)
self.pack()
widget = Button(self, text='Quit', command=self.quit)
widget.pack(expand=YES, fill=BOTH, side=LEFT)
def quit(self):
ans = askokcancel('Verify exit', "Really quit?")
if ans: Frame.quit(self)
class ScrolledText(Frame):
def __init__(self, parent=None, text='', file=None):
Frame.__init__(self, parent)
self.pack(expand=YES, fill=BOTH)
self.makewidgets()
self.settext(text, file)
def makewidgets(self):
sbar = Scrollbar(self)
text = Text(self, relief=SUNKEN)
sbar.config(command=text.yview)
text.config(yscrollcommand=sbar.set)
sbar.pack(side=RIGHT, fill=Y)
text.pack(side=LEFT, expand=YES, fill=BOTH)
self.text = text
def settext(self, text='', file=None):
if file:
text = open(file, 'r').read()
self.text.delete('1.0', END)
self.text.insert('1.0', text)
self.text.mark_set(INSERT, '1.0')
self.text.focus()
def gettext(self):
return self.text.get('1.0', END+'-1c')
class SimpleEditor(ScrolledText):
def __init__(self, parent=None, file=None):
frm = Frame(parent)
frm.pack(fill=X)
Button(frm, text='Save', command=self.onSave).pack(side=LEFT)
Button(frm, text='Cut', command=self.onCut).pack(side=LEFT)
Button(frm, text='Paste', command=self.onPaste).pack(side=LEFT)
Button(frm, text='Find', command=self.onFind).pack(side=LEFT)
Quitter(frm).pack(side=LEFT)
ScrolledText.__init__(self, parent, file=file)
self.text.config(font=('courier', 9, 'normal'))
def onSave(self):
filename = asksaveasfilename()
if filename:
alltext = self.gettext()
open(filename, 'w').write(alltext)
def onCut(self):
text = self.text.get(SEL_FIRST, SEL_LAST)
self.text.delete(SEL_FIRST, SEL_LAST)
self.clipboard_clear()
self.clipboard_append(text)
def onPaste(self):
try:
text = self.selection_get(selection='CLIPBOARD')
self.text.insert(INSERT, text)
except TclError:
pass
def onFind(self):
target = askstring('SimpleEditor', 'Search String?')
if target:
where = self.text.search(target, INSERT, END)
if where:
print where
pastit = where + ('+%dc' % len(target))
#self.text.tag_remove(SEL, '1.0', END)
self.text.tag_add(SEL, where, pastit)
self.text.mark_set(INSERT, pastit)
self.text.see(INSERT)
self.text.focus()
if __name__ == '__main__':
try:
SimpleEditor(file=sys.argv[1]).mainloop()
except IndexError:
SimpleEditor().mainloop()

——————————————

sinewave

#!/bin/bash
# plotsine.sh
# A DEMO to display a sinewave inside a standard bash terminal.
# Issued as Public Domain, 2014, B.Walker, G0LCU.
# Device: Macbook Pro 13", OSX 10.7.5, default bash terminal.
# Use variables so that you can see how it works.
angle=0
step_angle=5
vert_plot=0
horiz_plot=5
centreline=12
amplitude=11
PI=3.14159
clear
# Do a single cycle, quantised graph.
while [ $angle -le 359 ]
do
# Create each floating point value...
# CygWin now catered for... ;o)
vert_plot=$(awk "BEGIN{ printf \"%.12f\", ((sin($angle*($PI/180))*$amplitude)+$centreline)}")
#vert_plot=$(bc -l <<< "{print ((s($angle*($PI/180))*$amplitude)+$centreline)}")
# Truncate the floating point value to an integer then invert the plot to suit the x y co-ordinates inside a terminal...
vert_plot=$((24-${vert_plot/.*}))
# Plot the point(s) and print the angle at that point...
printf "\x1B["$vert_plot";"$horiz_plot"f*"
printf "\x1B[22;1fAngle is $angle degrees..."
sleep 0.1
# Increment values...
angle=$((angle+step_angle))
horiz_plot=$((horiz_plot+1))
done
printf "\x1B[23;1fSinewave plotted as a quantised text mode graph.\n"
exit 0

Change it into a cosine wave by changine line 9 from sine to cos.

vert_plot=$(awk “BEGIN{ printf \”%.12f\”, ((cos($angle*($PI/180))*$amplitude)+$centreline)}

cosine

——————————————

Original test page:

Screenshot from 2015-01-06 22:59:48

Copy files to your web server in one pass.

$ ssh typo1
eddie@typo1’s password:
Linux typo1 3.2.0-4-686-pae #1 SMP Debian 3.2.63-2+deb7u2 i686

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
You have new mail.
Last login: Tue Jan 6 04:37:43 2015 from oelt02.main

eddie@typo1:~$ cd /var/www
eddie@typo1:/var/www$ ls
eyeOS index.html
eddie@typo1:/var/www$ sudo mv index.html indexhtml.old
[sudo] password for eddie:

eddie@typo1:/var/www$ ls
eyeOS indexhtml.old
eddie@typo1:/var/www$ sudo scp eddie@oelt02:~/pwsrvr/* .
[sudo] password for eddie:
eddie@oelt02’s password:
1.gif 100% 7455 7.3KB/s 00:01
scp: /home/eddie/pwsrvr/backup: not a regular file
bash1.png 100% 55KB 55.5KB/s 00:00
bashscript.html 100% 805 0.8KB/s 00:00
scp: /home/eddie/pwsrvr/cgi-bin: not a regular file
cgi.gif 100% 3902 3.8KB/s 00:00
chmod.png 100% 51KB 50.9KB/s 00:00
cron.png 100% 49KB 49.3KB/s 00:00
ha.jpg 100% 7474 7.3KB/s 00:00
icon.ico 100% 1406 1.4KB/s 00:00
index.html 100% 4583 4.5KB/s 00:00
indexhtml.old 100% 91 0.1KB/s 00:00
ip.png 100% 67KB 66.5KB/s 00:00
scp: /home/eddie/pwsrvr/lo: not a regular file
sl.png 100% 73KB 72.9KB/s 00:00
sp.png 100% 102KB 102.5KB/s 00:00
ss.png 100% 33KB 32.9KB/s 00:00
thankyou1.php 100% 367 0.4KB/s 00:00
wmfb.dat 100% 261 0.3KB/s 00:00
wmfb.html 100% 781 0.8KB/s 00:00
wmfb.php 100% 565 0.6KB/s 00:00
eddie@typo1:/var/www$ ls
1.gif chmod.png icon.ico sl.png wmfb.dat
bash1.png cron.png index.html sp.png wmfb.html
bashscript.html eyeOS indexhtml.old ss.png wmfb.php
cgi.gif ha.jpg ip.png thankyou1.php

Reload the page and voila:

Screenshot from 2015-01-06 22:46:47

——————————————

Msp430 blinky (uses onboard led!)

EnergiaMainWindow

Get your Energia development package here: http://energia.nu/ /download/

LaunchPadMSP430G2452-v1.5

#include  <msp430g2553.h>
 unsigned int i = 0;          // Initialize variables. This will keep count of how many cycles between LED toggles
void main(void)
{
  WDTCTL = WDTPW + WDTHOLD;   // Stop watchdog timer. This line of code is needed at the beginning of most MSP430 projects.
                              // This line of code turns off the watchdog timer, which can reset the device after a certain period of time.
  P1DIR |= 0x01;              // P1DIR is a register that configures the direction (DIR) of a port pin as an output or an input.
                              // To set a specific pin as output or input, we write a '1' or '0' on the appropriate bit of the register.
                              // P1DIR = <PIN7><PIN6><PIN5><PIN4><PIN3><PIN2><PIN1><PIN0>
                              // Since we want to blink the on-board red LED, we want to set the direction of Port 1, Pin 0 (P1.0) as an output
                              // We do that by writing a 1 on the PIN0 bit of the P1DIR register
                              // P1DIR = <PIN7><PIN6><PIN5><PIN4><PIN3><PIN2><PIN1><PIN0>
                              // P1DIR = 0000 0001
                              // P1DIR = 0x01     <-- this is the hexadecimal conversion of 0000 0001
  for (;;)                    // This empty for-loop will cause the lines of code within to loop infinitely
  {
    P1OUT ^= 0x01;            // Toggle P1.0 using exclusive-OR operation (^=)
                              // P1OUT is another register which holds the status of the LED.
                              // '1' specifies that it's ON or HIGH, while '0' specifies that it's OFF or LOW
                              // Since our LED is tied to P1.0, we will toggle the 0 bit of the P1OUT register
    for(i=0; i< 20000; i++);  //Delay between LED toggles. This for-loop will run until the condition is met.
                              //In this case, it will loop until the variable i increments to 20000.
  }
}

——————————————

Home made fries. So good.

SUNP0023

Good day.

Ciao, 2014.

Leave a comment

Chit chat

======

Was installing a program on a server and found that the SQueL had an out of date command.

replaced TYPE=MyISAM  with ENGINE=MyISAM;

The tin I got for xmas that held a wallet will become a great microcontroller case.

Serial terminal can be a great repair tool. And also a text based monitor.

SUNP0038

—————————————

Web server software setup.

There are two basic programs we want to install. Apache2 the web server and PHP a programming language for use with the server.

$ sudo apt-get install apache2 php5 libapache2-mod-php5 php5-cli

That will take a little while to install. Be patient.

Then you need to do a fix for the server.

$ sudo nano /etc/apache2/conf.d/name

For example set add ServerName localhost or any other name:

ServerName localhost

or you could use

Servername yourservername

Save the file and restart Apache 2

$ sudo service apache2 restart

Test the server:

Point a browser to the RPi You should get the setup page.

Now we need to test the PHP install..

$ cd /var/www

You should already see index.html with the code that shows you the home page.

Now we need to create a new page

$ sudo nano phpinfo.php

Save and exit. Now point your browser to yourhostname/phpinfo.php

You should get the PHP status page.

Now you should be ready to roll.

Note: you may need to edit /etc/apache2/apache2.conf and add:

# add php useage
AddHandler application/x-httpd-php .html

Create your web page and save it at /var/www

Index.html

<html>
<head>
<title> main page </title>
</head>
<body>
<center>
<h2>
Site under contruction
</h2>
<hr>
<img src=’http://www.seemyheart.org/wp-content/uploads/2013/06/Website_Under_Construction.gif&#8217; eight=500 width=500 />

</center>
</body>
</html>

—————————————

Another table.

Screenshot from 2014-12-27 02:02:25

<!DOCTYPE html><html><head><style>thead {color:green;}
tbody {color:blue;}
tfoot {color:red;}
table,th,td
{border:1px solid black;}
</style>
</head>
<body>
<table border="1" style="width:300px">
<thead>
<tr>
<th>Name</th>
<th>Surname</th>
<th>Telephone</th>
</tr>
</thead>
<tbody>
<tr>
<td>Jack</td>
<td>Sales</td>
<td>555-5555</td>
</tr>
<tr>
<td>John</td>
<td>Admin</td>
<td>555-5555</td>
</tr>
<tr>
<td>James</td>
<td>Sales</td>
<td>555-5555</td>
</tr>
<tbody>
<tfoot>
<tr>
<td>Total</td>
<td>Total</td>
<td>Total</td>
</tr>
</tfoot>
</table>
</body>
</html>

—————————————

You are kind of like a computer and you need logical instructions to solve a problem. Those instructions are the programming that is needed. So what is it about?

Programming is required so that we can solve a problem.  What a lot of people think programming is about.

What are the parts of the system?  They are:

System parts
Component
People
Hardware
Data
Instructions Procedures Software Information

There is actually a lot more as you can see from the list below. I may differ from this list a bit.

We want to build a program, but first we have to see what we need. What are we looking for in results. Obviously you need to be organized. You need a plan.


Output:
What must the results look like?  Reports:hard copy, terminal, web output, or etc

Output datafiles:

Inputs:
How will we get the data into the system?

What form must the input data take:

How will we process the data from input to output:  Formulas and logic needed should be documented. Flowcharts are a way to document what your plans are. Two flowcharts of many used are first the Vtoc.

And then second is the traditional flowchart.

For specific symbols see: http://itcartoons.blogspot.com/2014/12/flow-chart-symbols.html



What hardware do we need?
There used to be a joke that you could not get fired for purchasing IBM with using the Intel platform. Nor so true anymore. Do need special input and or special output devices. What kind of networking. What kind of security equipment. In the past the computer hardware platform was dominated at least with the desktop systems if Intel versus PPC. The PPC platform has gone awaym but we now have the Arm processors really begin to flood the market. Arm is become the best for lighter platforms (embedded) and the Intel systems are taking the high end. That is changing now that the multicore Arm processors are more powerfull and easier to get.


What development software? 
What kind of software do we need. That goes not only for the development software, but for specialized firmware. For example,  Networking equipment comes with the manufacturers software. Many people choose to prefer third party software that is usually more powerful. We have seen that a lot with your home routers. Instead of the usual firmware, Openwrt or DDWrt may be used to replace the factory firmware.

One factor that is usually forgotten is how user friendly will the software be. Is it intuitive? How knowledgeable will the users already be. Hopefully they will they not be required to be constantly looking at manuals to use the software.

That being said development software, varies in the range of source code they prefer. C, Java, or many other languages might be used. What development language you might use also depends on the skill set of the program developers. Though more and more programmers are finally becoming diversified.

You might want to also consider how portable is the code going to be, can we reuse the code on newer or different platforms. What kind of software licenses will be required and other legal issues that might potentially arise. On a wide scale, will it be copyrighted or open source. Is there a chance that, there will be a question of ownership, as with Oracle and Java.

What data validation software and techniques need to be used to prevent problems. Or to quote and old addage of GIGO. (Garbage in then you will have  Garbage out).

Having decided all that, now we can start coding. Obviously as we go along, things will need to be changed. Source code should never be written in stone. You also want to make sure adequate backups or duplicates of the software are kept to prevent loss. One other issue is security. How sure are you the code will not get leaked to competitors either from inside or outside sources.


Testing and debugging. (expect the unexpected)
Lastly, what kinds of debugging tools and test data will we need to verify the competency of the software. When you think you have tested it enough, test it again. Will the dummy data be diverse enough to test all possible scenarios. Testing software will also need to be developed if not readily available.  One thing for sure is that even if you think everything is perfect, do not remove any existing systems till your new software proves to be robust. You would running software in tandem with the existing setup.

You may want to do testing, that forces the system to fail. You will be able to gauge what safeguards and others features need to be built in to easily recover from any possible disasters.

Have been in enough real world situations where everything was supposed to be perfect, but when the software was put into production, there were nothing but problems. Could tell quite a few war stories so to speak about installing new systems. Even if you do get it right, you may want to change how the software works or be able to additional equipment. That all requires redevelopment and retesting.

Documentation. (and training)
If potential users are made part of the testing process, you can gauge how user friendly your system is.  Then make changes as needed. Feedback from users can be a tool to also what needs to be part of the documentation of the project. Where did those users feel that they needed more instruction.

New users will also be a part of the documentation testing as what needs to also be included or improved as they are being trained on the software.  What are the proper procedures for the use of the software, handling of the equipment, and dealing with the data that is needed to get the information required.

End users will need to be trained as to whether the information generated by the system is valid. If the information in a form that is useful, how will the information be used. Was the problem solved with what was done? Here we go again.

—————————————
No matter how much wireless networking there is, you have to have at least a small amount of hardware. There are some tools that might be nice to have if you are using more than the minimal amount of cabling (aka hardwire).

The tone generator helps you trace where a wire is routed through. Personally, in all my years as a tech, I think we used on just once.

When trying to see if a network wall outlet was live, I used an end tester.

If things are working correctly, all four lights should be lit. Thought with this unit, have seen a few false positives.If all the light are not lit, it can be a bad female plug or some fault down the line. Generally has only one port.

To test a single cable, you would use a cable tester coupled to a patch cable (short length of network cable)..  You would not connect it to a network or it will get damaged. You will need access to both ends of a cable to test.

Generally these tools are used when preparing a cable. The unit will generally check one wire at a time. If the lights do not show in sequence then one or both ends of the cable have to be redone. If lights do not show up is also a symptom of a bad cable.

If all is well then you need to check to see if there is data coming down the line. There are some expensive tools, but usually a laptop with basic networking software tools will do just fine.  Generally, when you hook to a network, the network will send data in the form of TCPIP. will want to give a network address to use (sort of a phone number).  So we can find outby hooking the laptop whether that data has been sent.
If you are not getting an ipaddress you might see something like this:
$ ifconfig
eth0      Link encap:Ethernet  HWaddr 00:00:00:00:00:00
UP BROADCAST MULTICAST  MTU:1200  Metric:1
RX packets:77134 errors:0 dropped:0 overruns:0 frame:0
TX packets:59943 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:66488832 (66.4 MB)  TX bytes:9327481 (9.3 MB)
Then if the network is sending you an ipaddress, it might look something like this:
$ ifconfig
eth0      Link encap:Ethernet  HWaddr 00:00:00:00:00:00
inet addr:192.168.1.188 Bcast:192.168.1.255  Mask:255.255.255.0
UP BROADCAST RUNNING MULTICAST  MTU:1200  Metric:1
RX packets:77146 errors:0 dropped:0 overruns:0 frame:0
TX packets:59990 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:66490251 (66.4 MB)  TX bytes:9340858 (9.3 MB)
In this case then network address is 192.168.1.188 and everyone should be able to reach you at that network address.  But is the network available? You can use the ping command to see if a site is available. You get  to see Google network phone number.
$ ping -c1 http://www.google.com
PING http://www.google.com (173.194.37.50) 56(84) bytes of data.
64 bytes from atl14s07-in-f18.1e100.net (173.194.37.50): icmp_seq=1 ttl=53 time=30.0 ms— http://www.google.com ping statistics —
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 30.036/30.036/30.036/0.000 ms
You can go one step further and see what places are on the way to google
$ traceroute  http://www.google.com
or you can go to the web..

 

Lastly, you use special programs to see what kind of information is on the network. These are known as packet sniffers. One such program is Wireshark. These tools can also be used for wireless.

Also see: http://www.instructables.com/id/Lets-get-wired/
—————————————

Ever want to access your own site with a bit of privacy? Tunnelling can be a way to do that. It does require user rights on the intended machine to be the host. If yoy look at a web site, you see the normal url something.something. sitetype. In this case we are just going to oeorgan1. Bue what we would like to do is try to encrypt the connection between the two machines.

One traditional way to do it is using the secure shell (SSH) , but you could probably also use a program called putty.  Here is the simplest version:

ssh [-1246AaCfgkMNnqsTtVvXxY] [-b bind_address] [-c cipher_spec]
[-D port] [-e escape_char] [-F configfile] [-i identity_file] [-L
[bind_address:]port:host:hostport] [-l login_name] [-m mac_spec]
[-O ctl_cmd] [-o option] [-p port] [-R
[bind_address:]port:host:hostport] [-S ctl_path] [user@]hostname
[command]

$ sudo ssh  -L 80:localhost:80 eddie@oeorgan1

But if we did this it would open a prompt that I do not want.

if we use the -N will still let us in but there is no command prompt generated.

What we have done is point our localhost to another computer as if it was our own. So now if we use localhost as the url in the browser it shows the web page of the system we are connected to.

So now any communication should be encryped between the two machines. You can still go to other websites.

When we are done we can terminate the connect with a <ctrl>C.

So now if we go to localhost after refreshing the connection, the normal page should come up.

——————————————————————————-

Reverse SSH Tunneling Have you ever wanted to ssh to your Linux box that sits behind NAT? Now you can with reverse SSH tunneling. This document will show you step by step how to set up reverse SSH tunneling. The reverse SSH tunneling should work fine with Unix like systems. Let’s assume that Destination’s IP is 192.168.20.55 (Linux box that you want to access).  You want to access from Linux client with IP 138.47.99.99.  Destination (192.168.20.55) <- |NAT| <- Source (138.47.99.99) 1. SSH from the destination to the source (with public ip) using command below:

$ ssh -R 19999:localhost:22 sourceuser@138.47.99.99

* port 19999 can be any unused port.

2. Now you can SSH from source to destination through SSH tuneling:

$ ssh localhost -p 19999

3. 3rd party servers can also access 192.168.20.55 through Destination (138.47.99.99).  Destination (192.168.20.55) <- |NAT| <- Source (138.47.99.99)
<- Bob’s server 3.1 From Bob’s server:

$ ssh sourceuser@138.47.99.99

3.2 After the sucessful login to Source:

$ ssh localhost -p 19999

* the connection between destination and source must be alive at all time.

Tip: you may run a command (e.g. watch, top) on Destination to keep the connection active.

Typical session: (typo1 is the server)

Typo1
———————————————————–

inet addr:192.168.0.100  Bcast:192.168.0.255  Mask:255.255.255.0
inet6 addr: fe80::210:5aff:fe19:fd88/64 Scope:Link
UP BROADCAST RUNNING MULTICAST  MTU:1492  Metric:1
RX packets:858 errors:0 dropped:0 overruns:0 frame:0
TX packets:750 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:387860 (378.7 KiB)  TX bytes:99206 (96.8 KiB)
Interrupt:9 Base address:0x4800

inet addr:192.168.0.100  Bcast:192.168.0.255  Mask:255.255.255.0
inet6 addr: fe80::210:5aff:fe19:fd88/64 Scope:Link
UP BROADCAST RUNNING MULTICAST  MTU:1492  Metric:1
RX packets:858 errors:0 dropped:0 overruns:0 frame:0
TX packets:750 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:387860 (378.7 KiB)  TX bytes:99206 (96.8 KiB)
Interrupt:9 Base address:0x4800
eddie@typo1:~$ ssh -R 19999:localhost:22 eddie@192.168.1.126
eddie@192.168.1.126’s password:
Welcome to Ubuntu 14.04.1 LTS (GNU/Linux 3.13.0-43-generic i686)

* Documentation:  https://help.ubuntu.com/

No mail.
Last login: Tue Dec 30 21:01:52 2014 from dsl
eddie@oelt02:~$
eddie@typo1:~$ ssh -R 19999:localhost:22 eddie@192.168.1.126
eddie@192.168.1.126’s password:
Welcome to Ubuntu 14.04.1 LTS (GNU/Linux 3.13.0-43-generic i686)

* Documentation:  https://help.ubuntu.com/

No mail.
Last login: Tue Dec 30 21:01:52 2014 from dsl
eddie@oelt02:~$

oelt02:
————————————————————
$ ifconfig
eth0      Link encap:Ethernet  HWaddr 00:00:00:00:00:00
inet addr:192.168.1.126  Bcast:192.168.1.255  Mask:255.255.255.0
UP BROADCAST RUNNING MULTICAST  MTU:1200  Metric:1
RX packets:19375 errors:0 dropped:0 overruns:0 frame:0
TX packets:17998 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:7997509 (7.9 MB)  TX bytes:4431653 (4.4 MB)

lo        Link encap:Local Loopback
inet addr:127.0.0.1  Mask:255.0.0.0
inet6 addr: ::1/128 Scope:Host
UP LOOPBACK RUNNING  MTU:65536  Metric:1
RX packets:129 errors:0 dropped:0 overruns:0 frame:0
TX packets:129 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:18101 (18.1 KB)  TX bytes:18101 (18.1 KB)

eddie@oelt02:~$ ssh localhost -p 19999
eddie@localhost’s password:
Linux typo1 3.2.0-4-686-pae #1 SMP Debian 3.2.63-2+deb7u2 i686

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
You have new mail.
Last login: Tue Dec 30 03:16:31 2014

eddie@typo1:~$

—————————————

—————————————

If you need a fast setup web server running and you do not want to have to set up apache or something similar, then Python can help. Python comes with a simple builtin HTTP server. With the aid of this little HTTP server you can turn any directory (within limitations) in your system into your web server directory. This is important especially on embedded devices where storage is nominal. The only thing you need to have installed is Python. Linux comes with Python for the most part.

Practically speaking this is very useful to share files inside your local network. We like to use it for sharing documentation. Implementing this tiny but hugely useful HTTP server is very simple, its just a single line command. Note: this server is NOT SECURE. Use at your own risk.

Assume that I would like to share the directory /home/pwsrvr (or ~/pwsrvr) and my IP address is  192.168.1.200

Open up a terminal and type:

$ cd /home/your_dir_2_b_used
$ python -m SimpleHTTPServer 
 
or

c:\> cd /home/your_dir_2_b_used

c:\> python -m SimpleHTTPServer
That’s it! Now your http server will start in port 8000. You will get the message:
$ python -m SimpleHTTPServer 8080
Serving HTTP on 0.0.0.0 port 8080 ...
Now open a browser and type the following address:
http://192.168.1.200:8000

127.0.0.1 – – [28/Dec/2014 02:10:48] “GET / HTTP/1.1″ 200 –
127.0.0.1 – – [28/Dec/2014 02:10:48] “GET /ss.png HTTP/1.1″ 200 –
127.0.0.1 – – [28/Dec/2014 02:10:48] “GET /cgi.gif HTTP/1.1″ 200 –
127.0.0.1 – – [28/Dec/2014 02:10:48] “GET /ha.jpg HTTP/1.1″ 200 –

You can also access it via:


http://127.0.0.1:8000

If you want to use “localhost”, make sure it is set up in your hosts file. Seen where it was not. If the directory has a file named index.html, that file will be served as the initial file. If there is no index.html, then the files in the directory will be listed.

$ ls
1.gif            cgi-bin    ha.jpg         ip.png  ss.png         wmfb.php
backup           cgi.gif    icon.ico       lo      thankyou1.php
bash1.png        chmod.png  index.html     sl.png  wmfb.dat
bashscript.html  cron.png   indexhtml.old  sp.png  wmfb.html

Index.html has been renamed to text. If you just want to serve files, this might be a better way to do it.

If you wish to change the port that’s used start the program via:

$ python -m SimpleHTTPServer 8080

For more security, if you want to only serve on localhost you will need to write a custom Python program such as: (untested)

import sys
import BaseHTTPServer
from SimpleHTTPServer import SimpleHTTPRequestHandler

&lt;span class=&quot;nv&quot;&gt;HandlerClass&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; SimpleHTTPRequestHandler
&lt;span class=&quot;nv&quot;&gt;ServerClass&lt;/span&gt;  &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; BaseHTTPServer.HTTPServer
&lt;span class=&quot;nv&quot;&gt;Protocol&lt;/span&gt;     &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;HTTP/1.0&quot;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;if &lt;/span&gt;sys.argv&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;1:&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;:
    &lt;span class=&quot;nv&quot;&gt;port&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; int&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;sys.argv&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;1&lt;span class=&quot;o&quot;&gt;])&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;:
    &lt;span class=&quot;nv&quot;&gt;port&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; 8000
&lt;span class=&quot;nv&quot;&gt;server_address&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'127.0.0.1'&lt;/span&gt;, port&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;

HandlerClass.protocol_version &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; Protocol
&lt;span class=&quot;nv&quot;&gt;httpd&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; ServerClass&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;server_address, HandlerClass&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;nv&quot;&gt;sa&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; httpd.socket.getsockname&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt;
print &lt;span class=&quot;s2&quot;&gt;&quot;Serving HTTP on&quot;&lt;/span&gt;, sa&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;0&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;, &lt;span class=&quot;s2&quot;&gt;&quot;port&quot;&lt;/span&gt;, sa&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;1&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;, &lt;span class=&quot;s2&quot;&gt;&quot;...&quot;&lt;/span&gt;
httpd.serve_forever&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt;

&lt;/div&gt;

Note also that this should also work on MSWindows or MSWindows with Cygwin. Have not tried on an Apple Mac. you can find Python at https://www.python.org/downloads/
—————————————

Squacola – Boiled squash juices with carbonated water.

SUNP0032

Good day.

Almost the new year.

Leave a comment

Chit chat

=======

Did a fresh install of Debian Jessie and I noticed that the apache2 web document root has changed from /var/www/ to /var/www/html. Actually I did a wipe of the machine, Installed a guiless wheezy and then upgraded to jessie.

Been using the Sony usb 2x floppy disk drive to make to make pxe boot disks. Faster than the standard usb floppy. Yes, some of us still use floppies when you do not have nic cards that support ipxe scripts.

Always did pxeboot from the web server to boot linux installs, Decided to do it the old fashoined way.  Messed with tftp-hpa and isc-dhcp-server seem to be more trouble than they are worth. Just used Dnsmasq and everything worked well.

—————————————————-

Many people will disagree with me when I say the cloud is just a server. Clouds can be classified as public, private or hybrid, but that is what it really boils down to it is a machine or set of machines providing services over the web. Certainly you can argue that cloud can provide infrastructure, platform, and the traditional application services. Talked about some of these services in earlier articles.

However the internet is a network of systems that can be clearly defined. In the systems on the network can be can be described sort of like a road map or a set of telephone lines connected like below.

It may not be important exactly how they are put together, except that we know they are there. To know who is where either by what is known as a web address or an ipaddress (sort of phone number) allows you to access part of the cloud that you wish to connect to. It is impossible to know every phone number or ipaddress by heart, so the internet has a built in phonebook known as a Domain name server (aka dns). So when you type in http://www.google.com the dns translates that name into 74.125.227.238 and the networking equipment connects to Google for you. The dns can also assign phone numbers.  Why is that important?

Since a cloud can be as simple as one server, you could actually have a cloud in your own home or office with just a desktop and another computer. Generally the device that hooks you to the internet sort of acts like a local dns or telephone book.You can actually have several computers work together without having to actually access the larger real world internet.

You can have your own mini internet, but it is usually known as an intranet. With in that intranet you can set up your own server or servers just like the real internet. With your local servers, you might not even know the difference. You can use fancy expensive equipment to be your cloud servers, but to be honest, most any home computer like the one below will work just right.

Older computers are perfect for being a web server. In fact, on our web server, it has several sites that can be accessed from just one machine, just like they do in the real world. Those are known as virtual sites. For more information see: http://www.instructables.com/id/Uses-for-your-own-private-cloud/

Today many people use what is known as embedded devices to act as servers. They have a smaller foot print and use a lot less energy. We use the Cisco Linksys NSLU2 converted to run linux.

The Raspberry Pi, Beablebone Black, Pogoplug, and a variety of devices can also be used. It is not how big your system is, it is how you use it.

—————————————————-

Touchpads are great. The super portable computer.

You can spend several hundred dollars for the Microsoft  surface or save yourself some money if you have access to a Microsoft Windows desktop machine. All you need is a remote desktop software.  Accessing my old XP box with a touchpad.

Then again you can also access a linux server with the same software.

What is below the surface of your touchpad?

—————————————————-

Looks like the Chumby web site is back up again!

Other goodies:
http://www.instructables.com/id/Cheap-touchpad/
http://www.instructables.com/id/Cheap-touchpad-part-II/

—————————————————-

If you are only using command line systems, you have to use the keyboard as part of copying file method.

But there is actually, sort of an easier method. You will need to have the  following installed on the systems: openssh-server, fuser, and sshfs for starters.

The easiest way to set up a share is to go to the browser and use the sftp protocol (vs ftp or http) to point to the share.  Notice there are not shares set up yet. and again the file we want to copy is servers.txt.

Now you should see the share in the lower left hand side window.

Now you want to drag and drop the file.

—————————————————-

Ever copy code into vim and realize that the line numbers were also copied. Here is a quick easy way to get rid of the line numbers.

Original code:

We want to remove the first 5 characters from every line so then we need to use the normal option:

:%normal 5x

Press return and the line numbers are gone!

—————————————————-

A simple table using html

<table border="1" style="margin-left: auto; margin-right: auto; text-align: left; width: 500px;">
<tr> <th align="center" colspan="4">System parts</th></tr>
<tr align="center">
<td>
<b>Component</b></td> <td>
People
</td>
<td>
Hardware
</td>
<td>
Data
</td>
</tr>
<tr align="center">
<td>
<b>
Instructions
</b>
</td>
<td>
Procedures
</td>
<td>
Software
</td>
<td>
Information
</td>
</tr>
</table>
System parts
Component
People
Hardware
Data
Instructions Procedures Software Information

—————————————————-

Put old machines back to work as starter systems.
Yes Virginia, Slackware does run on a Pentium I with 256 meg ram.

# uname -a
Linux slacky 3.10.17 #2 Wed Oct 23 17:46:52 CDT 2013 i586 Pentium MMX GenuineIntel GNU/Linux
root@slacky:~# cat /proc/cpuinfo
processor : 0
vendor_id : GenuineIntel
cpu family : 5
model : 4
model name : Pentium MMX
stepping : 3
cpu MHz : 233.886
cache size : 0 KB
fdiv_bug : no
f00f_bug : yes
coma_bug : no
fpu : yes
fpu_exception : yes
cpuid level : 1
wp : yes
flags : fpu vme de pse tsc msr mce cx8 mmx
bogomips : 467.77
clflush size : 32
cache_alignment : 32
address sizes : 32 bits physical, 32 bits virtual
power management:

bootfloppy ==> local web server ==> slackware site (ftp://ftp.slackware.com/pub/slackware/slackware-14.1) ==> install

Local web server needs initrd.img and bzImage in an accessible directory. Dowloaded directly from Slackware. You could use the Slackware site locations instead.

Used a pxeboot floppy to point to the web server to get the install started. Of course, you can go to Romomatic.net to make the boot floppy. Use your own script, but this was the template to use for the script.

#!ipxe
dhcp any
initrd http://192.168.3.88/slack/initrd.img
chain http://192.168.3.88/slack/bzImage load_ramdisk=1 prompt_ramdisk=0 rw printk.time=0 nomodeset SLACK_KERNEL=huge.s

—————————————————-

Amazing what can be done with the NSLU2, A raid setup for the little unit!

—————————————————-

Rice, spinach, tuna, and Mandarin oranges for sweetness.

SUNP0025

Good day.

Happy new year.

Leave a comment

Chit chat

======

Combined entries from a cooking  and cartoon blog, so I have less to manage.

Looked at qb2c and bacon for converting basic language programs to C.  Found lots of issues and decided to keep using freebasic and qb64,

The poppler utilities are nice, but I still need to learn how to convert pdf to html to be good forblog entries.

There is a pcbasic emulator for linux:

Screenshot from 2014-12-18 20:05:30

—————————————-

Screenshot from 2014-12-18 14:15:13

Turn your computer into an old fashion clock.

gcc knrclock.c -lm -ncurses -o knrclock

invoke with:

$ ./knrclock

/*
* aclock – ascii clock for UNIX Console
*
* Copyright (c) 2002 Antoni Sawicki <tenox@tenox.tc>
* Version 1.8 (unix-curses); Dublin, June 2002
*
* Compilation: cc aclock-unix-knr.c -o aclock -lcurses -lm
*
* this is K&R version modified for old unices (but still with curses)
*
*/

#include <unistd.h>
#include <curses.h>
#include <math.h>
#include <time.h>

#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif

drw_cir(hand_max, sycen, sxcen, fonthw)
int hand_max; int sycen; int sxcen; int fonthw;
{
int x,y,r;
char c;

for(r=0;r<60;r++){
x=cos(r*M_PI/180*6)*hand_max*fonthw+sxcen;
y=sin(r*M_PI/180*6)*hand_max+sycen;
switch (r) {
case 0:
case 5:
case 10:
case 15:
case 20:
case 25:
case 30:
case 35:
case 40:
case 45:
case 50:
case 55:
c=’o';
break;
default:
c=’.';
break;
}
mvaddch(y,x,c);
}
}

draw_hand(minute, hlenght, c, sxcen, sycen, fonthw)
int minute; int hlenght; char c; int sxcen; int sycen; int fonthw;
{
int x,y,n;
float r=(minute-15)*(M_PI/180)*6;

for(n=1; n<hlenght; n++){
x=cos(r)*n*fonthw+sxcen;
y=sin(r)*n+sycen;
mvaddch(y,x,c);
}
}

main(){
char digital_time[15];
int fonthw = 2;
int sXmax, sYmax, smax, hand_max, sxcen, sycen;
long t;
struct tm *ltime;

initscr();

for(;;){
time(&t);
ltime=localtime(&t);
sXmax = COLS;
sYmax = LINES;

if(sXmax/2<=sYmax)
smax=sXmax/2;
else
smax=sYmax;

hand_max = (smax/2)-1;

sxcen = sXmax/2;
sycen = sYmax/2;

erase();
drw_cir(hand_max, sycen, sxcen, fonthw);

draw_hand((ltime->tm_hour*5)+(ltime->tm_min/10), 2*hand_max/3, ‘h’, sxcen, sycen, fonthw);
draw_hand(ltime->tm_min, hand_max-2, ‘m’, sxcen, sycen, fonthw);
draw_hand(ltime->tm_sec, hand_max-1, ‘.’, sxcen, sycen, fonthw);

mvaddstr(sYmax/4, sxcen-5, “.:ACLOCK:.”);
mvprintw(4*sYmax/5, sxcen-5, “[%02d:%02d:%02d]”, ltime->tm_hour, ltime->tm_min, ltime->tm_sec);

refresh();
sleep(1);
}
endwin();
}

—————————————-

Want to see what some of the earliest versions of linux were like? Go to: http://www.ibiblio.org/pub/historic-linux/distributions/

Early Debian came on three floppies!?! First you used the boot disk.

Start of a Debian install.

 One thing to remember is that back then linux supported scsi hard drives for the most part and not ide (pata) drives.

—————————————-
When I was young, we were fortunate that one of the classes we had to attend was learning to speed read. To have access to that software today can be very expensive. Here, we can sort of emulate that old software with a simple shell file program.

Screenshot from 2014-12-18 14:34:13

You can also build a teleprompter so you can create your own sort newsreader setup. Then you can have your own news show so the video can be uploaded to say Youtube or the like.

The code is very short and works extremely wel with short paragraphs. To invoke the software you will need the name of the file to be read and the delay to be used to determine the speed of the text to be displayed. You might want to start with .5 and then you can adjust as needed.

$ ./asciitextrdr.sh  asciifile2bread .5

#!/bin/sh

# A program to slowly cat file or standard input.

if [ “$1″ ] ; then
file=”$1″
else
file=”-”
fi
cat “$file” | while read c ; do
echo  “$c”
sleep  $2
done

[/code]

—————————————-

Screenshot from 2014-12-18 19:18:08

Manual CPM (use at your own risk) calculator at: http://groups.engin.umd.umich.edu/CIS/tinytools/cis375/f00/cpm/CPM%281%29.HTM

Screenshot from 2014-12-18 14:46:37

[From wikipedia]

The critical path method (CPM) is an algorithm for scheduling a set of project activities.

History

The critical path method (CPM) is a project modeling technique developed in the late 1950s by Morgan R. Walker of DuPont and James E. Kelley, Jr. of Remington Rand.[2] Kelley and Walker related their memories of the development of CPM in 1989.[3] Kelley attributed the term “critical path” to the developers of the Program Evaluation and Review Technique which was developed at about the same time by Booz Allen Hamilton and the U.S. Navy.[4] The precursors of what came to be known as Critical Path were developed and put into practice by DuPont between 1940 and 1943 and contributed to the success of the Manhattan Project.[5]

CPM is commonly used with all forms of projects, including construction, aerospace and defense, software development, research projects, product development, engineering, and plant maintenance, among others. Any project with interdependent activities can apply this method of mathematical analysis. Although the original CPM program and approach is no longer used, the term is generally applied to any approach used to analyze a project network logic diagram.

Basic technique

The essential technique for using CPM [6][7] is to construct a model of the project that includes the following:

  1. A list of all activities required to complete the project (typically categorized within a work breakdown structure),
  2. The time (duration) that each activity will take to complete,
  3. The dependencies between the activities and,
  4. Logical end points such as milestones or deliverable items.

Using these values, CPM calculates the longest path of planned activities to logical end points or to the end of the project, and the earliest and latest that each activity can start and finish without making the project longer. This process determines which activities are “critical” (i.e., on the longest path) and which have “total float” (i.e., can be delayed without making the project longer). In project management, a critical path is the sequence of project network activities which add up to the longest overall duration. This determines the shortest time possible to complete the project. Any delay of an activity on the critical path directly impacts the planned project completion date (i.e. there is no float on the critical path). A project can have several, parallel, near critical paths. An additional parallel path through the network with the total durations shorter than the critical path is called a sub-critical or non-critical path.

CPM analysis tools allow a user to select a logical end point in a project and quickly identify its longest series of dependent activities (its longest path). These tools can display the critical path (and near critical path activities if desired) as a cascading waterfall that flows from the project’s start (or current status date) to the selected logical end point.

Although the activity-on-arrow diagram (“PERT Chart”) is still used in a few places, it has generally been superseded by the activity-on-node diagram, where each activity is shown as a box or node and the arrows represent the logical relationships going from predecessor to successor as shown here in the “Activity-on-node diagram”.

Activity-on-node diagram showing critical path schedule, along with total float and critical path drag computations

In this diagram, Activities A, B, C, D, and E comprise the critical or longest path, while Activities F, G, and H are off the critical path with floats of 15 days, 5 days, and 20 days respectively. Whereas activities that are off the critical path have float and are therefore not delaying completion of the project, those on the critical path will usually have critical path drag, i.e., they delay project completion. The drag of a critical path activity can be computed using the following formula:

  1. If a critical path activity has nothing in parallel, its drag is equal to its duration. Thus A and E have drags of 10 days and 20 days respectively.
  2. If a critical path activity has another activity in parallel, its drag is equal to whichever is less: its duration or the total float of the parallel activity with the least total float. Thus since B and C are both parallel to F (float of 15) and H (float of 20), B has a duration of 20 and drag of 15 (equal to F’s float), while C has a duration of only 5 days and thus drag of only 5. Activity D, with a duration of 10 days, is parallel to G (float of 5) and H (float of 20) and therefore its drag is equal to 5, the float of G.

These results, including the drag computations, allow managers to prioritize activities for the effective management of project completion, and to shorten the planned critical path of a project by pruning critical path activities, by “fast tracking” (i.e., performing more activities in parallel), and/or by “crashing the critical path” (i.e., shortening the durations of critical path activities by adding resources).

Crash duration

“Crash duration” is a term referring to the shortest possible time for which an activity can be scheduled.[8] It is achieved by shifting more resources towards the completion of that activity, resulting in decreased time spent and often a reduced quality of work, as the premium is set on speed.[9] Crash duration is typically modeled as a linear relationship between cost and activity duration, however in many cases a convex function or a step function is more applicable.[10]

Expansion

Originally, the critical path method considered only logical dependencies between terminal elements. Since then, it has been expanded to allow for the inclusion of resources related to each activity, through processes called activity-based resource assignments and resource leveling. A resource-leveled schedule may include delays due to resource bottlenecks (i.e., unavailability of a resource at the required time), and may cause a previously shorter path to become the longest or most “resource critical” path. A related concept is called the critical chain, which attempts to protect activity and project durations from unforeseen delays due to resource constraints.

Since project schedules change on a regular basis, CPM allows continuous monitoring of the schedule, which allows the project manager to track the critical activities, and alerts the project manager to the possibility that non-critical activities may be delayed beyond their total float, thus creating a new critical path and delaying project completion. In addition, the method can easily incorporate the concepts of stochastic predictions, using the program evaluation and review technique (PERT) and event chain methodology.

Currently, there are several software solutions available in industry that use the CPM method of scheduling, see list of project management software. The method currently used by most project management software is based on a manual calculation approach developed by Fondahl of Stanford University.

Flexibility

A schedule generated using critical path techniques often is not realised precisely, as estimations are used to calculate times: if one mistake is made, the results of the analysis may change. This could cause an upset in the implementation of a project if the estimates are blindly believed, and if changes are not addressed promptly. However, the structure of critical path analysis is such that the variance from the original schedule caused by any change can be measured, and its impact either ameliorated or adjusted for. Indeed, an important element of project postmortem analysis is the As Built Critical Path (ABCP), which analyzes the specific causes and impacts of changes between the planned schedule and eventual schedule as actually implemented.

Start:
OPTION BASE 1
Array.size = 12
DIM E(Array.size), J$(Array.size), L(Array.size), P(Array.size, 12), S(Array.size, 2)
CLS
GOSUB Init
IF E$ = "Okay" THEN
GOSUB Early.starts
LET C = S(n, 1) + L(n)
GOSUB Late.starts
GOSUB Print.chart
GOSUB Print.table
END IF
END
The.end:

Init:
LET Interval = 5
LET E$ = "Okay"
READ n
DATA 7
FOR J = 1 TO n
READ L(J)
NEXT J
DATA 1,12,6,7,8,2,0
FOR J = 1 TO n
READ J$(J), P$
DO WHILE P$ <> "No more"
GOSUB Check.name
IF E$ = "Okay" THEN
LET P(J, K) = 1
READ P$
ELSE
RETURN
END IF
LOOP
NEXT J
IF J$(n) <> "End" THEN
PRINT "No end job"
LET E$ = "Not okay"
END IF
DATA "Begin","No more"
DATA "Shop","Begin","No more"
DATA "Prep","Shop","No more"
DATA "Salad","Shop","No more"
DATA "Cook","Prep","No more"
DATA "Serve","Cook","Salad","No more"
DATA "End","Serve","No more"
RETURN

Check.name:
LET E$ = "Okay"
FOR K = 1 TO J - 1
IF P$ = J$(K) THEN EXIT FOR
NEXT K
IF J = K THEN
PRINT P$; " does not precede "; J$(K); "."
LET E$ = "Not okay"
END IF
RETURN

Early.starts:
FOR J = 1 TO n
LET GE = 0
FOR K = 1 TO n
IF P(J, K) = 1 AND GE < E(K) THEN
LET GE = E(K)
END IF
NEXT K
LET S(J, 1) = GE
LET E(J) = GE + L(J)
NEXT J
RETURN

Late.starts:
FOR K = n TO 1 STEP -1
LET L = C
FOR J = 1 TO n
IF P(J, K) <> 0 AND L > S(J, 2) THEN
LET L = S(J, 2)
END IF
NEXT J
LET S(K, 2) = L - L(K)
NEXT K
RETURN

Print.chart:
PRINT TAB(35); "Time (in minutes)"
PRINT
PRINT "Job"; TAB(11); " 50 100 150 200"
PRINT " "; TAB(11); "----+----+----+----+----+----+----+----+"
FOR J = 2 TO n - 1
PRINT J$(J); TAB(11); "|";
LET K = S(J, 1)
IF S(J, 1) - S(J, 2) <> 0 THEN
DO WHILE K <= S(J, 1) + L(J) - 1
PRINT TAB(11 + K); "X";
LET K = K + 1
LOOP
DO WHILE K <= S(J, 2) + L(J) - 1
PRINT TAB(11 + K); ".";
LET K = K + 1
LOOP
ELSE
DO WHILE K <= S(J, 1) + L(J) - 1
PRINT TAB(11 + K); "C";
K = K + 1
LOOP
END IF
PRINT
NEXT J
PRINT
PRINT
RETURN

Print.table:
PRINT "Time of completion = "; C * Interval
PRINT
PRINT " Starts"
PRINT "Job Length Early Late Slack"
PRINT
FOR J = 2 TO n - 1
PRINT J$(J); TAB(10); L(J); TAB(25); S(J, 1);
PRINT TAB(32); S(J, 2); TAB(40); S(J, 2) - S(J, 1)
NEXT J
RETURN

—————————————-

Yet another way to convert binary to ascii.

Datafile af:
01000001 01010010 01010000 01000001 01001110 01000101 01010100

$ ./b2a1.sh af
ARPANET

<pre> #!/bin/bash

chrbin() {
        echo $(printf \\$(echo "ibase=2; obase=8; $1" | bc))
}

ordbin() {
  a=$(printf '%d' "'$1")
  echo "obase=2; $a" | bc
}

ascii2bin() {
    echo -n $* | while IFS= read -r -n1 char
    do
        ordbin $char | tr -d '\n'
        echo -n " "
    done
}

bin2ascii() {
    for bin in $*
    do
        chrbin $bin | tr -d '\n'
    done
}
while read z
do
bin2ascii $z
done < $1
echo

—————————————-

Yet another C program conversion to linux.

original code:

#include<stdio.h>
void main()
{
        int n,d=0,j,a[9];
        clrscr();
        printf("Enter the Integer which u want to Convert Decimal to Binary : ");
        scanf("%d",&n);
        while(n>0)
               {
                    a[d]=n%2;
                    n=n/2;
                    d++;
               }  
                    printf("After Converting Decimal to Binary is : ");
                    for(j=d-1;j>=0;j--)
                         printf("%d",a[j]);
                         getch();
}
Output ; Enter the Integer which u want to Convert Decimal to Binary : 8 After Converting Decimal to Binary is : 1000

Code for linux:


#include<stdio.h>
#include <unistd.h>
#include <termios.h>

char getch(){
char buf=0;
struct termios old={0};
fflush(stdout);
if(tcgetattr(0, &old)<0)
perror("tcsetattr()");
old.c_lflag&=~ICANON;
old.c_lflag&=~ECHO;
old.c_cc[VMIN]=1;
old.c_cc[VTIME]=0;
if(tcsetattr(0, TCSANOW, &old)<0)
perror("tcsetattr ICANON");
if(read(0,&buf,1)<0)
perror("read()");
old.c_lflag|=ICANON;
old.c_lflag|=ECHO;
if(tcsetattr(0, TCSADRAIN, &old)<0)
perror ("tcsetattr ~ICANON");
printf("%c\n",buf);
return buf;
}

void main()
{
int n,d=0,j,a[9];
// clrscr();
system("clear");
printf("Enter the Integer which u want to Convert Decimal to Binary : ");
scanf("%d",&n);
while(n>0)
{
a[d]=n%2;
n=n/2;
d++;
}
printf("After Converting Decimal to Binary is : ");
for(j=d-1;j>=0;j--)
printf("%d",a[j]);
getch();
}

—————————————-

The figure shows a schematic of the IR receiver circuit. The heart of the circuit is MOD1, an infrared detector module that removes the IR carrier frequency and transmits only the data that are encoded in the received IR signal. A suitable IR module is available at Radio Shack (No. 276-137 which is no longer sold). Might try Model: 276-640, but check the specs for sure. You probably could pull one from an old vcr.  The IR module needs a clean 5-V power supply, which is provided by IC1, a 7805 regulator. Power is supplied to the regulator by 9-V battery B1. The output of the module is wired to a male DB-25 multipin connector. The infrared detector module receives a signal, filters it, and removes the 40-kHz carrier. The output of the module is a TTL-level signal consisting of long and short pulses. The PC records those voltage levels over time, while the signal is being sent, and stores the data in a file. The line normally used by the PC’s printer port to indicate that the printer is out of paper (pin 12) is used in this project to accept data from the IR module. The I/O port is located at the address ox379. Bit 5 corresponds to input pin 12. Various software programs are required to let a PC store information input to its printer port.  The program stores the value it reads from the PC’s printer port into an array. When the input line is logic high, the ASCII character 1 is stored in the array. When the input line is logic low, ASCII character 0 is stored.

'**************************************************************************</p>
'* Program title  : Arco.bas

'* Date written   : original c code in 1994

'* Last Update    : August 1995

'* Language       : Basic

'* Written by     : eddie from Barry Hamilton's c code (C) 1994

'*                  in the Electonics Now - August 1995 issue

'* Written for    : Barry Hamilton and Electronics Now

'* Program intent : Monitor's out of paper input

'* I/O and files  : Pin 12 of the parallel printer port

'*                  irlog.raw

'*                  irlog.gph

'*                  irlog.fnl

'*-------------------------------------------------------------------------

'--------------------------------------------------------------------------

DEFINT A-Z

Zero = 0

One = 1

Two = 2

Fpin = One

Fpout = Two

Inchar = Zero

Lastchar = Zero

Totalcnt = Zero

Limit = 30000

DIM Store(Limit)

CONST The.Title = "Printer port pin 12 project"

ON ERROR GOTO Error.line

DO

CLS

PRINT

PRINT The.Title + "."

PRINT

PRINT "   A - Get data"

PRINT "   C - Convert data"

PRINT "   R - Report data"

PRINT "   Q - Quit"

PRINT

PRINT "choice: ";

z$ = " "

DO WHILE INSTR("ACRQ", z$) < 1

z$ = ""

DO WHILE z$ = ""

z$ = UCASE$(INPUT$(1))

LOOP

LOOP

PRINT z$

SELECT CASE z$

CASE "A"

GOSUB Dget

CASE "C"

GOSUB Dconvert

CASE "R"

GOSUB Dreport

CASE "Q"

EXIT DO

CASE ELSE

REM

END SELECT

LOOP

PRINT

PRINT "The end!"

END

'--------------------------------------------------------------------------

Dget:

Timedelay = Zero

Sloop = One

Skey = Zero

Cntr1 = Zero

Cntr2 = Zero

Cindata = Zero

Fpout$ = ""

Escape.key = 27

CLS

PRINT

PRINT The.Title + ": I/R Get."

PRINT

INPUT "Enter time delay  : ", Timedelay

IF Timedelay < Zero THEN

Timedelay = 20

END IF

INPUT "      outfile name: ", Fpout$

IF LCASE$(Fpout$) = "" THEN

Fpout$ = "irlog.raw"

END IF

PRINT

PRINT "Opening "; LCASE$(Fpout$); " for output."

OPEN Fpout$ FOR OUTPUT AS #Fpout

PRINT "Gathering data with a time delay of "; LTRIM$(RTRIM$(STR$(Timedelay))); "."

DO WHILE Sloop = One

PRINT TAB(5); "Start: "; TIME$

FOR Cntr1 = Zero TO Limit - One

Cindata = INP(&H379)

IF (Cindata AND 32) <> Zero THEN

Store(Cntr1) = ASC("1")

ELSE

Store(Cntr1) = ASC("0")

END IF

FOR Cntr2 = One TO Timedelay

NEXT Cntr2

NEXT Cntr1

PRINT TAB(5); "Ending: "; TIME$

PRINT "Writing data to "; LCASE$(Fpout$); "."

PRINT #Fpout, "[";

FOR Cntr1 = Zero TO Limit - One

PRINT #Fpout, CHR$(Store(Cntr1));

NEXT Cntr1

PRINT #Fpout, "]";

PRINT "Press escape to quit and any other key to continue";

PRINT ":"

BEEP

Skey = ASC(INPUT$(One))

IF Skey = Escape.key THEN

EXIT DO

END IF

LOOP

PRINT "Closing "; LCASE$(Fpout$); "."

CLOSE #Fpout

RETURN

'--------------------------------------------------------------------------

Dconvert:

Fpin$ = ""

Fpout$ = ""

Nlimit = 80

S2$ = ""

One$ = STRING$(9, "1")

Zero$ = STRING$(9, "0")

S11$ = ""

S10$ = ""

FOR Cntr = One TO Eight

S11$ = S11$ + One$ + "+"

S10$ = S10$ + Zero$ + "+"

NEXT Cntr

CLS

PRINT

PRINT The.Title + ": I/R Graph."

PRINT

INPUT "Enter name of infile : ", Fpin$

IF Fpin$ = "" THEN

Fpin$ = "irlog.raw"

END IF

INPUT "              outfile: ", Fpout$

IF Fpout$ = "" THEN

Fpout$ = "irlog.gph"

END IF

PRINT

PRINT "Opening file: "; Fpin$; " for input."

OPEN Fpin$ FOR INPUT AS #Fpin

PRINT "Opening file: "; Fpout$; "for output."

OPEN Fpout$ FOR OUTPUT AS #Fpout

PRINT

Zline = CSRLIN

DO WHILE NOT EOF(Fpin)

Inchar = ASC(INPUT$(1, #Fpin))

LOCATE Zline, One

PRINT "Examining: "; CHR$(Inchar);

IF Inchar = ASC("0") AND Lastchar = ASC("0") THEN

Totalcnt = Totalcnt + One

END IF

IF Inchar = ASC("1") AND Lastchar = ASC("1") THEN

Totalcnt = Totalcnt + One

END IF

IF Lastchar = ASC("[") THEN

Totalcnt = One

END IF

IF Lastchar = ASC("]") THEN

Totalcnt = Zero

END IF

IF Inchar = ASC("0") AND Lastchar = ASC("1") THEN

IF Totalcnt < Nlimit THEN

S2$ = ""

S2$ = LEFT$(S2$ + S11$, Totalcnt)

PRINT #Fpout, S2$

ELSE

PRINT #Fpout, "        | ";

PRINT #Fpout, USING "####"; Totalcnt;

PRINT #Fpout, "1"

END IF

Totalcnt = One

END IF

IF Inchar = ASC("1") AND Lastchar = ASC("0") THEN

IF Totalcnt < Nlimit THEN

S2$ = ""

S2$ = LEFT$(S2$ + S10$, Totalcnt)

PRINT #Fpout, S2$

ELSE

PRINT #Fpout, "        | ";

PRINT #Fpout, USING "####"; Totalcnt;

PRINT #Fpout, "0"

END IF

Totalcnt = One

END IF

IF Inchar = ASC("]") AND Lastchar = ASC("0") THEN

IF Totalcnt < Nlimit THEN

S2$ = ""

S2$ = LEFT$(S2$ + S10$, Totalcnt)

PRINT #Fpout, S2$

ELSE

PRINT #Fpout, "        | ";

PRINT #Fpout, USING "####"; Totalcnt;

PRINT #Fpout, "0"

END IF

Totalcnt = Zero

END IF

IF Inchar = ASC("]") AND Lastchar = ASC("1") THEN

IF Totalcnt < Nlimit THEN

S2$ = ""

S2$ = LEFT$(S2$ + S11$, Totalcnt)

PRINT #Fpout, S2$

ELSE

PRINT #Fpout, "        | ";

PRINT #Fpout, USING "####"; Totalcnt;

PRINT #Fpout, "1"

END IF

Totalcnt = Zero

END IF

Lastchar = Inchar

LOOP

PRINT

PRINT "Closing "; LCASE$(Fpout$); "."

CLOSE #Fpout

PRINT "Closing "; LCASE$(Fpin$); "."

CLOSE #Fpin

RETURN

'--------------------------------------------------------------------------

Dreport:

Cmark = One

Cspace = Zero

Maxzero = Zero

Maxone = Zero

Syncstate = Zero

Fpin$ = ""

Fpout$ = ""

CLS

PRINT

PRINT The.Title + ": I/R Final."

PRINT

PRINT "(M)ark or (S)pace Sync: ";

z$ = " "

DO WHILE INSTR("MS", z$) < 1

z$ = ""

DO WHILE z$ = ""

z$ = UCASE$(INPUT$(1))

LOOP

LOOP

PRINT z$

SELECT CASE z$

CASE "M"

Syncstate = Mark

CASE "S"

Synstate = Space

END SELECT

INPUT "Enter the maxzero factor : ", Maxzero

INPUT "      the maxone  factor : ", Maxone

INPUT "      the file for input : ", Fpin$

IF Fpin$ = "" THEN

Fpin$ = "irlog.raw"

END IF

INPUT "      the file for output: ", Fpout$

IF Fpout$ = "" THEN

Fpout$ = "irlog.fnl"

END IF

PRINT

OPEN Fpin$ FOR INPUT AS #Fpin

PRINT "Opening file: "; Fpin$; " for input."

OPEN Fpout$ FOR OUTPUT AS #Fpout

PRINT "Opening file: "; Fpout$; " for output."

PRINT

Zline = CSRLIN

DO WHILE NOT EOF(Fpin)

Inchar = ASC(INPUT$(One, #Fpin))

LOCATE Zline, One

PRINT "Examining: "; CHR$(Inchar);

IF Inchar = ASC("0") AND Lastchar = ASC("0") THEN

Totalcnt = Totalcnt + One

END IF

IF Inchar = ASC("1") AND Lastchar = ASC("1") THEN

Totalcnt = Totalcnt + One

END IF

IF Lastchar = ASC("[") THEN

Totalcnt = One

END IF

IF Lastchar = ASC("]") THEN

Totalcnt = Zero

END IF

IF Inchar = ASC("0") AND Lastchar = ASC("1") THEN

IF Syncstate = Space THEN

IF Totalcnt <= Maxzero THEN

PRINT #Fpout, "0";

END IF

IF Totalcnt > Maxzero AND Totalcnt < Maxone THEN

PRINT #Fpout, "1";

END IF

IF Totalcnt >= Maxone THEN

PRINT #Fpout, "        | ";

PRINT #Fpout, USING "####"; Totalcnt;

PRINT #Fpout, "1="

END IF

END IF

Totalcnt = One

END IF

IF Inchar = ASC("1") AND Lastchar = ASC("0") THEN

IF Syncstate = Mark THEN

IF Totalcnt <= Maxzero THEN

PRINT #Fpout, "0";

END IF

IF Totalcnt > Maxzero AND Totalcnt < Maxone THEN

PRINT #Fpout, "1";

END IF

IF Totalcnt >= Maxone THEN

PRINT #Fpout, "        | ";

PRINT #Fpout, USING "####"; Totalcnt;

PRINT #Fpout, "0="

END IF

END IF

Totalcnt = One

END IF

IF Inchar = ASC("]") AND Lastchar = ASC("0") THEN

PRINT #Fpout, "        | ";

PRINT #Fpout, USING "####"; Totalcnt;

PRINT #Fpout, "0]"

Totalcnt = Zero

END IF

IF Inchar = ASC("]") AND Lastchar = ASC("1") THEN

PRINT #Fpout, "        | ";

PRINT #Fpout, USING "####"; Totalcnt;

PRINT #Fpout, "1]"

Totalcnt = Zero

END IF

Lastchar = Inchar

LOOP

PRINT

PRINT "Closing "; LCASE$(Fpout$); "."

CLOSE #Fpout

PRINT "Closing "; LCASE$(Fpin$); "."

CLOSE #Fpin

RETURN

'--------------------------------------------------------------------------

Error.line:

END

'*******************************************************

—————————————-

From oatmeal flakes

SUNP0142

To fake flour.

SUNP0100

Good day.

Older Entries

Follow

Get every new post delivered to your Inbox.