snej.de

^(my digital playground)

Xilinx ML300 and Virtex-II Pro Development on Ubuntu Desktop 14.04.1, Debian 7.6.0 and OS X

| Comments

Recently, I tried to implement a design for the Xilinx ML300 board which is an approx. 12 years old FPGA development board. It is built around the Virtex-II Pro XC2VP7 FPGA which holds a physical PowerPC 405 processor inside ready to be routed to some logic.

Well, I ran into some dead ends while setting up the the Xilinx Design Tools on Ubuntu 14.04.1 to be able to work with the Virtex-II pro. Officially, only RHEL 4/5 and SUSE LE 10 are supported but I found the following way to get everything working.

I have tested these steps successfully with following setups:

  • Ubuntu 14.04.1 Desktop 32-bit
    • as guest OS under OS X 10.9.4 with VirtualBox 4.3.14 (incl. Extension Pack)
  • Ubuntu 14.04.1 Desktop 64-bit
    • as guest OS under OS X 10.9.4 with VirtualBox 4.3.14 (incl. Extension Pack)
    • as main OS
  • Debian 7.6.0 64-bit
    • as main OS

Here are the steps:
1. Get the proper version of the design tools
2. Install ISE & EDK
3. Configure the environment
4. Check if ISE works
5. Check if EDK works
6. Platform Cable USB
7. Verify by programming the FPGA

1. Get the proper version of the design tools

The latest release of the Vivado or ISE Design Tools do not support the Virtex-II Pro architecture. So, don’t waste time and bandwidth by downloading it. The latest support for the Virtex-II Pro is within the ISE Design Tools 10.1 Service Pack 3. You have to download and install ISE 10.1 and the Service Pack 3 separately from xilinx.com. The ISE and EDK tarballs include support for 32- and 64-bit systems. The Service Pack 3 update comes in zip files. Some zips are valid for both architectures and some zips are separately available for 32- and 64-bit. Be sure to get the right ones for your system.

At the download page for ISE 10.1 there is a link named “Obtain a v10.1 Registration ID”. If you don’t have a Registration ID then you can get one for free there.

Note: If you are not familiar with the Xilinx Design Tools, here is a short summary. The ISE Design Tools is the classical tools package from Xilinx. The most important parts are ISE Foundation (just called ISE) and the Embedded Development Kit (EDK). ISE allows implementing logic by using VHDL, Verilog and schematics. The EDK provides a GUI called Xilinx Platform Studio (XPS), a SDK for PowerPC and MicroBlaze and a catalog of IP-cores. The EDK uses ISE and allows system level design. Don’t get confused: the terms EDK and XPS are often used synonymously. Also, consider that these notes explain the naming conventions for the ISE Design Tools 10.1 and not any earlier or later release.

2. Install ISE & EDK

When extracting the downloaded tar files do not extract to a Windows- or a Mac- filesystem. This will destroy the installer consistency. The installer GUI will look garbled and it will tell you that your Registration ID is not valid. This is very very very misleading and annoying. Simply extract the tar and zip files somewhere beneath your home directory, which should be an ext4 filesystem if you are on Ubuntu-14.04.1. Also, don’t use spaces in the path where the installers are extracted to. Otherwise you’ll get an error message saying your processor platform is not supported.

All archives contain a programm called setup in the root of the archive. Simply run it with ./setup. There is no need to use sudo for the installion as long as you install it somewhere in your home directory. The directory I use is /home/jens/Xilinx/10.1.

When installing ISE and EDK do not select to install the cable drivers. It won’t work with your kernel. We will catch up on this later.

3. Configure the environment

After the installation of ISE and EDK each installer will show you some environment variables that have to be set for ISE and EDK. These are stored as shell scripts in:

~/Xilinx/10.1/ISE/settings32.sh
~/Xilinx/10.1/EDK/settings32.sh

on 64-bit OS:

~/Xilinx/10.1/ISE/settings64.sh
~/Xilinx/10.1/EDK/settings64.sh

For EDK, both have be sourced (see next step). For ISE, just the ISE script is sufficient.

Additionally, there are some manual steps to do for EDK:

Crucial for EDK’s functionality is to create symlinks for gmake and libdb-4.1.so:

sudo ln -s /usr/bin/make /usr/bin/gmake

on Ubuntu desktop 14.04.1 64-bit:

sudo ln -s /usr/lib/x86_64-linux-gnu/libdb-5.3.so /usr/lib/x86_64-linux-gnu/libdb-4.1.so

on Debian 7.6.0 64-bit:

sudo ln -s /usr/lib/x86_64-linux-gnu/libdb-5.1.so /usr/lib/x86_64-linux-gnu/libdb-4.1.so

on Ubuntu desktop 14.04.1 32-bit:

sudo ln -s /usr/lib/i386-linux-gnu/libdb-5.3.so /usr/lib/i386-linux-gnu/libdb-4.1.so

Also very useful: Install xpdf and create a symlink with the name acroread to it. EDK offers a button to open the PDF datasheet for the IP-core you are currently editing/viewing. It tries to open the PDF file with acroread, which is not available on Ubuntu. So we want to use xpdf instead:

sudo apt-get install xpdf
sudo ln -s xpdf /usr/bin/acroread

Finally, the EDK is using a $LANGUAGE variable but the same variable is set to your default locale by Ubuntu, e.g. en_US. Thus, EDK will throw a lot of warnings during synthesis, so we have to unset it with unset LANGUAGE before starting EDK. I put this at the end of the settings32.sh respectively settings64.sh of EDK with:

On a 32-bit OS:

echo "unset LANGUAGE" >>  ~/Xilinx/10.1/EDK/settings32.sh

…or on 64-bit OS:

echo "unset LANGUAGE" >>  ~/Xilinx/10.1/EDK/settings64.sh

Now, on 64-bit OS, install libc6-i386:

sudo apt-get install libc6-i386

Finally, change the default shell to bash:

sudo ln -sf bash /bin/sh

4. Check if ISE works

Now, let’s start ISE from the shell with:

source Xilinx/10.1/ISE/settings32.sh
ise

…or if you are on 64-bit OS:

source Xilinx/10.1/ISE/settings64.sh
ise

The first line executes ISE’s setting script in the context of our shell and makes necessary environment variables available to ISE.

NOTE: Randomly, I got a “Segmentation fault (core dumped)” message and ISE returned early. The solution was to disable the “Tip of the Day” feature. BTW, this note would make a great Tip of the Day!

Now, let’s check if ISE really works by creating a new design and light up the first LED in GPIO2/TEST area on the ML300 board:

  • Create a new project with HDL as top-level source type
  • Set the device properties according to the target hardware.
    In case of the ML300 that is:
    • Product Category: General Purpose
    • Family: Virtex2P
    • Device: XC2VP7
    • Package: FF672
    • Speed: -6
    • TOP-Level Source Type: HDL
    • Synthesis Tool: XST (VHDL/Verilog)
    • Simulator: Modelsim-SE Mixed
    • Preferred Language: VHDL
    • Enable Enhanced Design Summary: YES
    • Enable Message Filtering: NO
    • Display Incremental Messages: NO
  • Create two new source files:
    • VHDL Module “top.vhd”
    • Implementation Constraints File: “top.ucf”
top.vhd
1
2
3
4
5
6
7
8
9
10
11
12
13
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity top is
    Port ( led : out  STD_LOGIC );
end top;

architecture Behavioral of top is
begin
  led <= '1';
end Behavioral;
top.ucf
1
2
# T8 is connected the first LED in the GPIO2/TEST area.
NET "led"  LOC = "T8"  |  IOSTANDARD = LVCMOS33;

Right-click “Generate Programming File” and select “Run” to initiate the process of generating a programming file for the FPGA. The ISE console should print

Process "Generate Programming File" completed successfully

if the process finished and there should be a top.bit file in your project directory, which is the programming file you just generated. In step 7 we will upload it to the FPGA to verify if it works as expected.

5. Check if EDK works

We start EDK, respectively XPS, from the shell with

source Xilinx/10.1/ISE/settings32.sh
xps

…or if you are on 64-bit OS:

source Xilinx/10.1/ISE/settings64.sh
xps

We are asked to create a new or open an existing project. Let’s create a new project with the Base System Builder wizard:

  • Choose to a directory to store the project file (many files will be generated there, so I reommend to create a new directory)
  • Select to create new design for the Xilinx ML300 board
  • Select the PowerPC as processor
  • Keep the PowerPC configuration as preselected
  • With the next four pages “Configure IO Devices” deselect everything but RS232_Uart_1
  • Click next on the following pages, then generate and finish
  • Select Device Configuration from the menu, then Update Bitstream

Now, the EDK creates a system.bit file for the hardware design (similar step as for the top.bit in ISE). Then, it builds the example applications and merges them with the system.bit to a file named download.bit. This new bitstream contains the FPGA logic utilizing the PowerPC core, including software which will be put into the FPGA’s block ram area. When everything is ready you should read “Done!” in ISE’s output console. In step 7 we will upload it to the FPGA to verify if it works as expected.

6. Platform Cable USB

To get the Xilinx Platform Cable USB working we need an alternative for the official drivers from Xilinx because they won’t work with the current kernel. Luckily, a guy named Michael Gernoth solved this issue by implementing a library called libusb-driver, which emulates the original driver. As stated on his page, this should work with more cables than just the Platform Cable USB. However, I only have this one available.

The following commands will get and install Michael’s cable drivers:

sudo apt-get install git libusb-dev fxload
cd ~/Xilinx
git clone git://git.zerfleddert.de/usb-driver
cd usb-driver
make

Then on a 32-bit Ubuntu or Debian:

source ~/Xilinx/10.1/ISE/settings32.sh
./setup_pcusb

… or on 64-bit OS:

source ~/Xilinx/10.1/ISE/settings64.sh
./setup_pcusb

Now, we set the LD_PRELOAD environment variable and test our cable connection with iMPACT:

export LD_PRELOAD=/home/jens/Xilinx/usb-driver/libusb-driver.so
impact
  • Double-click “Boundary Scan”
  • Right click in the big white area which is labeled “Right click to Add Device or Initialize JTAG chain”
  • Select “Cable Auto Connect”

If you didn’t get any error and if the iMPACT console doesn’t say “Cable autodetection failed.” then everything is fine.

I appended the line with LD_PRELOAD at the end of the settings32.sh respectively settings64.sh of ISE with:

echo "export LD_PRELOAD=/home/jens/Xilinx/usb-driver/libusb-driver.so" >> ~/Xilinx/10.1/ISE/settings32.sh

respectively:

echo "export LD_PRELOAD=/home/jens/Xilinx/usb-driver/libusb-driver.so" >> ~/Xilinx/10.1/ISE/settings32.sh

7. Verify by programming the FPGA

To verify all previous steps we will program our FPGA by using the programming files top.bit (generated with ISE) and download.bit (generated with EDK).

Start iMPACT from the shell with:

source xilinx_env
impact
  • Double-click “Boundary Scan”
  • Right click in the big white area which is labeled “Right click to Add Device or Initialize JTAG chain”
  • Select “Initialize Chain”
  • The first device in the chain is the ACE controller, which we don’t want to programm. Click “Bypass”
  • Now we are asked to select a configuration file for the FPGA. Browse and select the top.bit file generated by ISE and click “Open”.
  • The next window asks if we want to add additional files for block RAM information and software executables. We don’t want that. Click “OK” twice.
  • iMPACT shows the JTAG chain and indicates that top.bit is associated to the xc2vp7 device, which is the FPGA
  • Right-click xc2vp7 and select “Program” to start the programming procedure.
  • The “FPGA done” LED on the ML300 should light up within some seconds to indicate that the FPGA has been programmed. Same for the first LED in the GPIO2/TEST area because that what we told in our little example above with led <= '1'.

Now, right-click the xc2vp7 device and select “Assign New Configuration File”. Remove top.bit and add the download.bit file generated by EDK and click “Open”. The file is in the subdirectory impelementation/ of your EDK project directory.

Hook up a serial RS232 connection to the first RS232 port of the ML300 board and observe the output at 9600,8,n,1. Then right-click the xc2vp7 device and select “Program” to start the programming procedure. After programming the FPGA you should see:

-- Entering main() --
-- Exiting main() --

If so, well done. You’ve set up an environment ready to develop for the ML300 and Virtex-II Pro. It works directly with Ubuntu Desktop 14.04.1 64-bit, Debian 7.6.0 64-bit as well as virtual machine with VirtualBox under OS X 10.9.4 with VirtualBox 4.3.14 (incl. Extension Pack).

Top 5 Swift Features Briefly Explained: Closures, Generics, Type Inference, Multiple Return Types and Namespaces

| Comments

When announcing Swift at the WWDC 2014 on Monday (see Swift announced), five features of the new language have been highlighted during the presentation:

  • Closures
  • Generics
  • Type inference
  • Multiple return types
  • Namespaces

Closures
Closures are functions that have access to all data that are in scope of where the closure has been created (e.g. local variables of the function that created the closure). If that data is out of scope for any other function - e.g. the creator of the closure is a function that already has returned - then the data is still alive because the closure set a reference to this data. Thus, the garbage collection won’t trash this data, even if it was a local variable inside a function that has returned. Of course, assuming there is any reference to the closure itself.

  • Closures are comparable to local classes in Java.
  • Closures are similar to blocks in Objective-C.

Generics
Generics allow program code to be independent from the data types by its variables. For example, a function that uses parameters as input data doesn’t have to know for what kind of data type it is written for. Basically, the function is simply generic for any type of data.

  • Generics are similar to Templates in C++.
  • Objective-C is a dynamically typed language. That means the compiler does’t always check for correct types. It’s the programmer’s duty. Generics make sense in strongly typed languages like Swift where the Compiler will warn about wrong types. Thus, it’s less error-prone during runtime.

Type inference
Type inference allows to omit the type of variables. Based on the expression, Swift concludes the type automatically. However, the programmer can explicitly specify the type.

  • Type inference seems identical as in Python.
  • Objective-C does not support type inference.

Multiple return types
A function’s return type can be a tuple with multiple values and types.

  • Usage of arrays, structs, lists, etc. can be used to achieve multiple return types in almost every language. Swift’s approach with tuples is comparable to returning tuples in Python.
  • Objective-C does not support tuples but structs or special container classes can be used for this purpose.

Namespaces
A Namespace allows to group together a bunch of identifiers which all belong to the same library, package or functionality in general. Thus, namespaces avoid naming collisions. Otherwise, modern software projects that include libraries from different developers and vendors would have a hard job to assure that no class name occurs twice within the project. Interestingly, I did not find the namespace feature in Swift. Even the documentation does not contain the word “namespace”.

  • C++ use namespaces; Java calls them packages; Python organizes namespaces by modules.
  • Objective-C does not support namespaces. That is why the classes have prefixes in their filenames like NSString or UIButton. This is typical kind of workaround when namespaces are no available.

Swift Announced

| Comments

At Apple’s WWDC on Monday, 2nd June, 2014, Craig Federighi announced a new programming language called Swift. The main focus shall be:

  • Fast
  • Modern
  • Safe
  • Interactive

Especially the last point was emphasized as “a level of interactivity in development that you’ve never seen on a platform“. Federighi announced Swift as faster:

  • Complex object:
    • Swift: 3.9x<
    • Objective-C: 2.8x<
    • Python: 1x
  • RC4 encryption:
    • Swift: 220x
    • Objective-C: 127x
    • Python: 1x

But actually, Federighi did not compare Swift against Objective-C. Instead, he compared Swift and Objective-C with reference to Python. Thus, giving extrem high values. One could say, he compares apples to oranges since Python is run by an interpreter while Swift is compiled to native code. Also, Swift and Objective-C are used in totally different domains than Python. I don’t think that anyone will ever use Swift where Python has been used before. Otherwise, drop me a line and I will update this article.

The benchmark for Swift with reference to Objective-C would be this:

  • Complex object sort: 139% the speed of Objective-C
  • RC4 encryption: 173% the speed of Objective-C

However, at the end it’s all processor instructions and we don’t know how the performed benchmarks were implemented and optimized. Since Federighi just said faster without explicitly mentioning runtime, maybe the speed comparison was meant about the typing of source code. In that unlikely event, I really wonder who wrote the Python code.

The really interesting fact seems that Swift combines two great things:
1. The speed of native code, like Objective-C.
2. The functionality and ease of a modern high-level language like Python.

So, what’s the catch? Anyone?

oneLineSystemMon: Simple Geeklet That Shows Cpu, Memory, Disk and Transferred Network Data

| Comments

When working with Linux you may be used to have a system monitor on your desktop like Conky or its ancestor Torsmo. If you are on OS X then you might like to use GeekTool for this purpose.

I put together a script for GeekTool that fits my needs. It will show up as a single line of text on your desktop and shows the load of your CPU, memory, disk and the transferred data on your network interfaces. The output is:

CPU 4.87% – MEM 5179M – SSD 70% – LAN IN:0 Bytes OUT:0 Bytes – WIFI IN:101.531 MiB OUT:13.687 MiB

If you wonder about the green and red color… this is just for my personal convenience to be able to quickly distinguish incoming and outgoing data.

You need a small python script called valueToIeee1541String.py to show the transferred bytes of the network interfaces in human readable format – e.g. “1.804 GiB” instead of “1936614762”. You can get it from here https://github.com/jewirth/valueToIeee1541String. Please put in in ~/bin to make the geeklet work or edit the geeklet manually.

Download the Geeklet: https://github.com/jewirth/oneLineSystemMon Geeklets are associated with GeekTool which should start automatically when opening a Geeklet.

GeekTool can handle much more nice stuff than printing one line from a shell script. Google for “Geeklets” and have fun.

Update: I added a second Geeklet to my desktop directly below the above on. It shows the netstat output but only with certain socket states including ‘listening’. It’s too simple to provide a Geeklet file for this one. You just have to add a new Shell GeekLet with the following command in a single line:

netstat -a | grep -e ESTAB -e LIST -e CLOS -e SYN_ -e LAST_ -e _ACK -e FIN_ -e TIME_

This is how my two Geeklets will appear:

images

 

Raspberry Pi: Setting Up a Wifi Connection Without Keyboard, Mouse and Monitor Connected

| Comments

Unlike Ethernet, which is configured to automatically use DHCP on the RPi (Raspberry Pi) by default, setting up a Wifi connection can be difficult to some users. First of all, the RPi can not and should not guess the name of your Wifi network and it surely can’t do so with your Wifi passphrase. I hope you really do not want this.

Now, setting up Wifi can be simple by using the graphical interface and the provided application on the desktop named “Wifi Config”. But this ‘simple’ requires you to have a HDMI display and a USB keyboard/mouse ready to be connected. If not, then you can attach your RPi to your router via an Ethernet cable, then connect via ssh to the command line and then configure your Wifi remotely. Below, this procedure is described in more detail.

Step 1 - Requirements

  • Raspberry Pi with Raspbian “wheezy”
  • Ethernet cable
  • Router
  • A computer which is already connected to your router
  • SSH client software (for Windows systems you can use PuTTY, MacOS and GNU/Linux systems are usually equipped with such a client software)

Step 2 - Set Up

Connect your RPi to the router using the Ethernet cable and power on the RPi.

Step 3 - Get the IP address of your RPi

Boot it up and figure out the IP address of your RPi. Since we don’t have anything but power and ethernet connected to the RPi we can do so by checking the administration utilities of our router or by doing a ping sweep. Another possibility explained by Remi Bergsma is to scan for the specific range of ethernet addresses used by the RPi boards.

Step 4 - Connect via SSH

Use the SSH Client software to connect to your RPi. On MacOS X and GNU/Linux systems you can do so by opening the Terminal application and entering the command ssh pi@192.168.1.101. In this case the IP address is 192.168.1.101 and the username/password are the default ones (username: pi password: raspberry). The password will be requested by the SSH client while the connection is established. macy:~ jens$ ssh pi@192.168.1.101 pi@192.168.1.101’s password:

Step 5 - Wifi Settings

Now you should have access to the command line of your RPi. Type sudo nano /etc/network/interfaces to edit the network interface configuration file. You should see something similar like this:

/etc/network/interfaces
1
2
3
4
5
6
7
8
9
10
11
auto lo

iface lo inet loopback
iface eth0 inet dhcp

allow-hotplug wlan0
auto wlan0
iface wlan0 inet manual
wpa-roam /etc/wpa_supplicant/wpa_supplicant.conf

iface default inet dhcp

We need to put the information about our Wifi network name and it’s WPA passphrase into this configuration file. Edit your file analogue to this example:

/etc/network/interfaces mark:8-10
1
2
3
4
5
6
7
8
9
10
11
12
13
auto lo

iface lo inet loopback
iface eth0 inet dhcp

allow-hotplug wlan0
auto wlan0
iface wlan0 inet dhcp
 wpa-ssid "MyHomeNetwork"
 wpa-psk "YourWpaPassphraseGoesHere"
wpa-roam /etc/wpa_supplicant/wpa_supplicant.conf

iface default inet dhcp

Save the file and close it.

Step 6 - Verify

Verify your changes by rebooting the system with

sudo shutdown -r now

On success, the RPi should automatically connect to your Wifi network on startup. Please note that your router’s DHCP server won’t assign the same IP address to the Wifi connection of the RPi as it did before with the ethernet connection. Therefore, repeat Step 3.

If you figured out the new IP address you should be able to talk to your RPi as usual (SSH, ping, and so on).

If you have any questions or improvements please feel free to do so. You can use the “Post a comment” feature below. I’ll try to answer and update this article where necessary.




Comment from Anonymous: cwpa_supplicant: wpa-roam can only be used with the “manual” inet METHOD

Jingle Bells Playing Light-up Piano Keyboard

| Comments

Christmas time is just around the corner and so is the next tinkering project:

it has to do something with Christmas…
it has to do something with software…
it has to do something with electronics…

…Ermm, so the first idea was to put a bunch of colourful LEDs around a Christmas tree. Indeed, that is innovative as putting coloured paper around a gift. So I came up with the idea to make a jingle bells playing light-up piano keyboard by utilizing …well, a tree and LEDs but additionally there‘ll be a speaker ;o)

So, here‘s a little sketch about the idea.

images

The first challenge is the keyboard design. We need to know how to play jingle bells on a keyboard. As you might know or see on YouTube tutorials, there are several ways to play this song. The easiest way is to use a single note at a time by just playing the melody of verse and chorus. The lowest key I used for playing is a D and the highest key is the E on the next octave. Between those two keys we also need E, Fis, G, A, B, C, D (on the next octave). But keep in mind, you could also transpose the melody to higher or lower notes. So, after figuring out which keys we need I started drawing a keyboard in Gimp. To make things easier, I wrote the name of the note on each key and marked the notes that have to be player with a red dot. Some more keys than necessary a there for a clean look.

images

Now that we have finished the outer design of the keyboard we need the interior. There was a small non-etched copper circuit board in the tinkering box since years. So this is a good starting point. We can carve a circuit (respectively the boundaries of the tracks) into the copper board by using a box cutter. Then, soldering small SMD LEDs and resistors across the tracks (right over the cut of the box cutter) to connect them to the appropriate nets. This doesn’t only sound like a mess but it also looks like a mess.

images

Now let‘s put the keyboard design and some descriptions on this messy photo to see what has been done here. Since very small SMD parts were used its quite hard to see. Yes, it‘s even harder to solder. Be a little smarter than me and use bigger parts :–)

images

Here is an approbate schematic design.

images

The next thing to prepare is a speaker. If you are lucky you find one in an old walkie talkie device, phone, toy, etc. My speaker looks like this.

images

I decided to use a NPN-transistor to connect and disconnect the speaker to the voltage source. The idea is to do this with a frequency that equals the musical notes of the song. This will result in a square wave sound which is the very loud and sharp. R1 is used to make the sound more quiet. Push a jumper at position X1 to get out the maximum volume but be sure your speaker can handle the power :–)

images

Now it‘s time to put things together. We have 9 control lines for the LEDs and 1 line for the speaker signal. We want the device to start playing if a push button is pressed and when done playing the device shall be switch off automatically. For this, we use a pushbutton in parallel to a relay switch which is controller by the ATmega. If someone presses the push button then the ATmega starts running and holds the relay closed. This way the user who pushes the button only has to hold for a few milliseconds until the system runs. If the song has been played then the ATmega shall release the relay signal so that the relay opens and the battery gets disconnected.

images

The electronic part is ready, now it‘s time for the software to put life inside. The song is an array of 16-bit values (uint16_t song[]) and each value represents the wave period of the appropriate piano key sound. Now, the software just has to iterate through the array, light up the appropriate LED and change the PWM settings according to the current value as read from the array. Additionally, there is a delay function for the timing to switch off the PWM between the notes to make it sound like as if the piano keys are pushed down and released in a very simple rhythm. Here is the source code.

main.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
 #define F_CPU    1000000UL

 #include <avr/io.h>
 #include <util/delay.h>

 #define C    3817
 #define CIS  3610
 #define D    3401
 #define DIS  3215
 #define E    3030
 #define F    2865
 #define FIS  2703
 #define G    2550
 #define GIS  2410
 #define A    2273
 #define AIS  2146
 #define H    2024
 #define C2   1906
 #define D2   1701
 #define E2   1515

 // jingle bells ...to me it is!  
 uint16_t song[] = {
   D,  H,  A,  G, D,   0,  0,  D,  H,  A,  G,  E,  0, 0,
   E,  C2, H,  A, FIS, 0,  0,  D2, D2, C2, A,  H,  0, 0,
   D,  H,  A,  G, D,   0,  0,  D,  H,  A,  G,  E,  0, 0,
   E,  C2, H,  A, D2,  D2, D2, D2, E2, D2, C2, A,  G, 0, D2, 0,
   H,  H,  H,  0, H,   H,  H,  0,  H,  D2, G,  A,  H, 0,
   C2, C2, C2, 0, C2,  H,  H,  0,  H,  A,  A,  H,  A, 0, D2, 0,
   H,  H,  H,  0, H,   H,  H,  0,  H,  D2, G,  A,  H, 0,
   C2, C2, C2, 0, C2,  H,  H,  0,  H,  D2, D2, C2, A, G,
 };

 void play(uint16_t sound)
 {
   // sound output  
   ICR1 = sound & 0xFFFE; // set period  
   OCR1A = (sound & 0xFFFE) >> 2; // set pulse width  

   // led output  
   switch(sound)
   {
     case D:   PORTD = 0x01;  break;
     case E:   PORTD = 0x02;  break;
     case FIS: PORTD = 0x04;  break;
     case G:   PORTD = 0x08;  break;
     case A:   PORTD = 0x10;  break;
     case H:   PORTD = 0x20;  break;
     case C2:  PORTD = 0x40;  break;
     case D2:  PORTD = 0x80;  break;
     case E2:  PORTB = 0x01;  break;
     default:
       PORTD = 0;
       PORTB = 0;
       break;
   }
 }

 int main (void)
 {
   uint8_t i;
   DDRB = 0x03;  // speaker and relais are outputs  
   DDRD = 0xFF;  // LED 1 to 8 are outputs  
   DDRC = (1<<PC5); // LED 9 is an output  
   PORTC = (0<<PC5); // keep the relais of life tight!  
   TCCR1A = (1<<COM1A1) | (1<<COM1A0) | (1<<WGM11); // pwm settings
   TCCR1B = (1<<WGM13) | (1<<WGM12) | (1<<CS10);  // pwm settings

   for(i=0; i<(sizeof(song)/sizeof(uint16_t)); i++)
   {
     play(song[i]); // play note, switch LED on  
     _delay_ms(200);
     play(0);    // mute sound, switch LED off  
     _delay_ms(20);
   }

   PORTC = (1<<PC5);  // release the relais of life...

   return 0;
 }

A small fake fir tree that can be found in a typical decoration store besides tons of other useless stuff makes a great stand for the keyboard and gives a real Christmas touch to it.

images

Now, here is my realization of the plans above. The front side shows the keyboard and a push button. The push button is at the bottom in between the red ribbon.

images

The back side shows the 9 volts battery, the speaker and the perfboard which holds the ATmega, the 7805 voltage regulator, the capacitor, the transistor and two resistors.

images

You may wonder where the relay is gone. I only had a 250V relay in my tinkering box which is kinda big. So I fixed it with a cable tie to the tree. Indeed, this is like using a sledgehammer to crack a nut but the part was already there :–) If you have a better idea (like a solid state relay?) which works fine for this application then please let me know!

images

Here is a video of the tree in action. Unfortunately, in the video it is quite hard to see that the LED illuminates one key instead of all keys nearby. This looks better in reality.

SpartanPong

| Comments

Just out of curiosity, I tried to create a VGA signal with the Xilinx Spartan-3E Starter Kit. It all ended up as a Pong game with some funny behavior. Feel free to download the project files (created with Xilinx ISE WebPack 12.1) or just watch the video. The project runs at 640x480@60Hz. I learned about the VGA signal timing from here and of course by playing around a lot ;o)




Comment from Anonymous: can you please explain why you thoroughly how you ball is moving?and why you took the cnt value=5000??

Answer: I suppose you mean 50000, right? Well, that’s the speed of the animation as I preferred it. As you can read in the comment above “animation rate = 25 MHz / 50000 = 500 pixels per second”. So, 50000 is the amount of cycles I have to wait to get a result of 500 pixels per second. The less I wait, the faster the animation goes. So, increasing this value slows down the animation speed. Play with the value ;)