Fun with VGA graphics in C
Dr_Acula
Posts: 5,484
I've managed to port Kye's VGA driver into C.
Video drivers use a lot of memory, and with 19200 bytes needed for a 160x120 display there isn't much room left for code in Spin. One solution is to use Catalina and shift the code into external memory. This frees up over 30k of hub space that can be used for all sorts of things including video and intercog communications, and also means there is up to 512k of code space. It will run on boards that can run Catalina in external memory, including the Dracblade (see website link at the bottom of this page).
This is hopefully the first of many translations of Obex code into C.
First the code boots up into Catalina in text mode with a white on blue text screen. This is very useful for debugging code. Then the code finds which cog is running C and stops all the other cogs. Then it loads a video driver into one cog and starts displaying things.
Code ends up rather similar to Spin/PASM with PASM largely staying the same and Spin translated to C. I'm using an IDE that does some preprocessing to glue the Pasm to the C code, but in the end it produces standard Catalina code.
Catalina has the 'main' at the end of the program, so this is the main code:
The code below is getting rather large, and it could be shortened by using #include .h instead of pasting the .h file into the code. I've written it as a large text file so it can be posted here. In future things like bitmaps could be stored on an SD card rather than as data in the program.
I'm looking forward to getting Catalina to do more interesting things, including loading and reloading cogs to switch video drivers within code.
I'd love some input from C programmers, as my C programming is not that great!
Video drivers use a lot of memory, and with 19200 bytes needed for a 160x120 display there isn't much room left for code in Spin. One solution is to use Catalina and shift the code into external memory. This frees up over 30k of hub space that can be used for all sorts of things including video and intercog communications, and also means there is up to 512k of code space. It will run on boards that can run Catalina in external memory, including the Dracblade (see website link at the bottom of this page).
This is hopefully the first of many translations of Obex code into C.
First the code boots up into Catalina in text mode with a white on blue text screen. This is very useful for debugging code. Then the code finds which cog is running C and stops all the other cogs. Then it loads a video driver into one cog and starts displaying things.
Code ends up rather similar to Spin/PASM with PASM largely staying the same and Spin translated to C. I'm using an IDE that does some preprocessing to glue the Pasm to the C code, but in the end it produces standard Catalina code.
Catalina has the 'main' at the end of the program, so this is the main code:
void main ()
{
int i;
clearscreen();
printf("Clock speed %u \n",_clockfreq()); // see page 28 of the propeller manual for other useful commands
printf("Catalina running in cog number %i \n",_cogid()); // integer
sleep(4000); // for CRT display to warm up
stopallcogs(); // stop all cogs except C one
vga160(7); // start graphic driver in cog 7
displayclear(); // clear the display
plotbox(0,0,159,119,rgb(255,0,0)); // draw a box in red round edges
displayicon(50,50); // display 32x32 picture of Tweety
plotbox(49,49,82,82,rgb(0,255,0)); // draw a box around the picture
while (1); // Prop reboots on exit from main()
}
The code below is getting rather large, and it could be shortened by using #include .h instead of pasting the .h file into the code. I've written it as a large text file so it can be posted here. In future things like bitmaps could be stored on an SD card rather than as data in the program.
I'm looking forward to getting Catalina to do more interesting things, including loading and reloading cogs to switch video drivers within code.
I'd love some input from C programmers, as my C programming is not that great!
/* PASM demo for use with Catalina IDE Precompiler and Compiler */
#include <stdio.h>
/* Global constants for both C and PASM */
const unsigned long int graphicstart = 100; // start of space for video graphics buffer - problems if less than 100 but must be under 512
const unsigned long int displayindicator_const = 19998; // 19200 plus a buffer (tile drivers might use more)
const unsigned long int syncindicator_const = 19999; // used by the graphics code
/* End global constants */
/* PASM Code for compilation using SpinC and inclusion as a data file
PASM Start vga160.spin
CON
directionstate_const = $00FF0000 ' for pin group 2
videostate_const = $30_00_04_FF ' for pin group 2
frequencystate_const = 337914606 ' calculated for 80Mhz
_clkfreq = 80_000_000 ' 5Mhz Crystal
_clkmode = xtal1 + pll16x ' x 16
' Start of C hub constants
graphicstart = 100
displayindicator_const = 19998
syncindicator_const = 19999
' End of C constants
PUB Main
coginit(1,@initialization,0) ' cog 1 dummy, cogstart, dummy value see Loop replaced par with #0
DAT
org 0
initialization mov vcfg, videoState ' Setup video hardware.
mov frqa, frequencyState '
movi ctra, #%0_00001_101 '
mov displayindicatoraddress, #1 ' startup value
' /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
' Active Video
' /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
loop mov displayCounter, #graphicstart ' buffer starts at graphicstart must be < 9 bits value ie <512 so 0 is the logical choice
mov tilesCounter, #120 '
tilesDisplay mov tileCounter, #4 ' Set/Reset tile fill counter.
tileDisplay mov vscl, visibleScale ' Set/Reset the video scale.
mov counter, #40 '
' //////////////////////Visible Video//////////////////////////////////////////////////////////////////////////////////////////
videoLoop rdlong buffer, displayCounter ' Download new pixels.
add displayCounter, #4 '
or buffer, HVSyncColors ' Update display scanline.
waitvid buffer, #%%3210 '
djnz counter, #videoLoop ' Repeat.
' //////////////////////Invisible Video////////////////////////////////////////////////////////////////////////////////////////
mov vscl, invisibleScale ' Set/Reset the video scale.
waitvid HSyncColors, syncPixels ' Horizontal Sync.
' //////////////////////Repeat/////////////////////////////////////////////////////////////////////////////////////////////////
sub displayCounter, #160 ' Repeat.
djnz tileCounter, #tileDisplay '
add displayCounter, #160 ' Repeat.
djnz tilesCounter, #tilesDisplay '
' /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
' Inactive Video
' /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
add refreshCounter, #1 ' Update sync indicator.
wrbyte refreshCounter, syncIndicatorAddress '
' //////////////////////Front Porch////////////////////////////////////////////////////////////////////////////////////////////
mov counter, #11 ' Set loop counter.
frontPorch mov vscl, blankPixels ' Invisible lines.
waitvid HSyncColors, #0 '
mov vscl, invisibleScale ' Horizontal Sync.
waitvid HSyncColors, syncPixels '
djnz counter, #frontPorch ' Repeat # times.
' //////////////////////Vertical Sync//////////////////////////////////////////////////////////////////////////////////////////
mov counter, #(2 + 2) ' Set loop counter.
verticalSync mov vscl, blankPixels ' Invisible lines.
waitvid VSyncColors, #0 '
mov vscl, invisibleScale ' Vertical Sync.
waitvid VSyncColors, syncPixels '
djnz counter, #verticalSync ' Repeat # times.
' //////////////////////Back Porch/////////////////////////////////////////////////////////////////////////////////////////////
mov counter, #31 ' Set loop counter.
backPorch mov vscl, blankPixels ' Invisible lines.
waitvid HSyncColors, #0 '
mov vscl, invisibleScale ' Horizontal Sync.
waitvid HSyncColors, syncPixels '
djnz counter, #backPorch ' Repeat # times.
' //////////////////////Update Display Settings////////////////////////////////////////////////////////////////////////////////
rdbyte buffer, displayIndicatorAddress wz ' Update display settings.
muxnz dira, directionState '
' //////////////////////Loop///////////////////////////////////////////////////////////////////////////////////////////////////
jmp #loop ' Loop.
' /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
' Data
' /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
invisibleScale long (16 << 12) + 160 ' Scaling for inactive video.
visibleScale long (4 << 12) + 16 ' Scaling for active video.
blankPixels long 640 ' Blank scanline pixel length.
syncPixels long $00_00_3F_FC ' F-porch, h-sync, and b-porch.
HSyncColors long $01_03_01_03 ' Horizontal sync color mask.
VSyncColors long $00_02_00_02 ' Vertical sync color mask.
HVSyncColors long $03_03_03_03 ' Horizontal and vertical sync colors.
' //////////////////////Configuration Settings//////////////////////////////////////////
directionState long directionstate_const
videoState long videostate_const
frequencyState long frequencystate_const
' //////////////////////Addresses//////////////////////////////////////////////////////////////////////////////////////////////
displayIndicatorAddress long displayindicator_const
syncIndicatorAddress long syncindicator_const ' global constant
' //////////////////////Run Time Variables/////////////////////////////////////////////////////////////////////////////////////
counter res 1
buffer res 1
tileCounter res 1
tilesCounter res 1
refreshCounter res 1
displayCounter res 1
' /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
fit 496
PASM End
*/
void vga160(char cognumber) // unique name for each loader
{
/**
* @file vga160_array.h
* Created with spin.binary PASM to C Array Converter.
* Copyright (c) 2011, John Doe
*/
unsigned long vga160_array[] =
{
0xa0bffc33, 0xa0bff434, 0x58fff00d, 0xa0fc6a01,
0xa0fc7864, 0xa0fc7478, 0xa0fc7204, 0xa0bffe2c,
0xa0fc6e28, 0x08bc703c, 0x80fc7804, 0x68bc7031,
0xfc7c70e4, 0xe4fc6e09, 0xa0bffe2b, 0xfc3c5e2e,
0x84fc78a0, 0xe4fc7207, 0x80fc78a0, 0xe4fc7406,
0x80fc7601, 0x003c7636, 0xa0fc6e0b, 0xa0bffe2d,
0xfc7c5e00, 0xa0bffe2b, 0xfc3c5e2e, 0xe4fc6e17,
0xa0fc6e04, 0xa0bffe2d, 0xfc7c6000, 0xa0bffe2b,
0xfc3c602e, 0xe4fc6e1d, 0xa0fc6e1f, 0xa0bffe2d,
0xfc7c5e00, 0xa0bffe2b, 0xfc3c5e2e, 0xe4fc6e23,
0x02bc7035, 0x7cbfec32, 0x5c7c0004, 0x000100a0,
0x00004010, 0x00000280, 0x00003ffc, 0x01030103,
0x00020002, 0x03030303, 0x00ff0000, 0x300004ff,
0x14242aee, 0x00004e1e, 0x00004e1f
};
unsigned long hub_array[512];
unsigned long par_cogject[] = { 1, 2, 3 }; // data to pass to cog - ignore if not used
int i;
for (i = 0; i < 512; i++)
{
hub_array[i] = vga160_array[i];
}
_coginit((int)par_cogject>>2, (int)hub_array>>2, cognumber); // load into cog
}
void pset(int x, int y, char pixelcolor) // set pixel at x,y to color %RRGGBBxx x=0 to 159, y=0 to 119
{
int address = graphicstart + x + (y * 160); // calculate the address - no boundary checks as slows down code
*((char *)address) = pixelcolor; // poke to this location in hub memory
}
char rgb(char red, char green, char blue) // pass red etc 0-255, reduces to 0-3, combines to pixelcolor
{
char pixelcolor;
red = red >> 6; // divide by 64
green = green >> 6;
blue = blue >> 6;
pixelcolor = (red << 6) | (green << 4) | (blue << 2); // combine together using shifts then or bits
return pixelcolor;
}
void plotbox(int x1, int y1, int x2, int y2, char pixelcolor) // plot a box, or a line eg horizontal line y1=y2
{
int x;
int y;
for (x=x1; x<=x2 ;x++)
{
pset(x,y1,pixelcolor); // horizontal lines
pset(x,y2,pixelcolor);
}
for (y=y1+1; y < y2; y++)
{
pset(x1,y,pixelcolor); // vertical lines
pset(x2,y,pixelcolor);
}
}
void displayclear() // clears to black
{
int address;
char pixelcolor = 0; // black
for (address=graphicstart; address < graphicstart+19200; address++)
{
*((char *)address) = pixelcolor; // set to pixelcolor
}
}
// ---------------------------- end vga 160x120 driver methods ------------------------------------------------
void displayicon(int x,int y) // 32x32 bit icon created from the Visual IDE tab and copied here. Display at x,y
{
int r;
int c;
int i;
// File c:\program files\catalina\demos\tweety32.h
char tweety[] =
{
0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc,
0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc,
0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc,
0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc,
0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xf8, 0xf8, 0xf8, 0xf8, 0xac, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc,
0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xf8, 0xf4, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf4, 0xf8, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc,
0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xf8, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf4, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc,
0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xf8, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc,
0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xf4, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf4, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc,
0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xe0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf8, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc,
0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xf8, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xa0, 0xe0, 0xe0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf4, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc,
0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xf8, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xe4, 0xa8, 0xa4, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xe0, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc,
0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xa8, 0xfc, 0xb8, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xe0, 0xe4, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc,
0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xf4, 0xf0, 0xf0, 0xf0, 0xf0, 0x68, 0xac, 0xb8, 0xf0, 0xf0, 0xf0, 0xa4, 0xa4, 0xa4, 0xf4, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc,
0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xf8, 0xf0, 0xf0, 0xf0, 0xf0, 0x18, 0x68, 0xa8, 0xf0, 0xf0, 0xa8, 0xfc, 0xa8, 0xe0, 0xf8, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc,
0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xf4, 0xf0, 0xf0, 0xf0, 0x18, 0x68, 0xf4, 0xf0, 0xa4, 0x6c, 0xbc, 0xe4, 0xf8, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc,
0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xf8, 0xf0, 0xf0, 0xf0, 0xa4, 0xa8, 0xf0, 0xf0, 0x14, 0x68, 0xe4, 0xf8, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc,
0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xf8, 0xf0, 0xf0, 0xf0, 0xf0, 0xe0, 0xe0, 0x58, 0xe4, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc,
0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xf8, 0xf0, 0xf0, 0xf0, 0xe0, 0xe4, 0xe0, 0xf0, 0xf4, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc,
0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xf8, 0xf4, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf4, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc,
0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xf0, 0xf4, 0xf8, 0xf8, 0xf8, 0xf4, 0xf8, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc,
0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xf8, 0xf0, 0xf0, 0xfc, 0xfc, 0xf4, 0xf0, 0xf8, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc,
0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xe4, 0xf0, 0xf0, 0xf4, 0xfc, 0xf4, 0xf0, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc,
0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xf8, 0xe0, 0xf0, 0xf0, 0xf0, 0xf0, 0xe0, 0xf8, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc,
0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xf8, 0xe0, 0xa0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc,
0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xf4, 0xf0, 0xf8, 0xf0, 0xf0, 0xf0, 0xf4, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc,
0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xe4, 0xe4, 0xf0, 0xf4, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc,
0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xf8, 0xe4, 0xe4, 0xe4, 0xf8, 0xfc, 0xfc, 0xfc, 0xe4, 0xe8, 0xe4, 0xfc, 0xfc, 0xf8, 0xe8, 0xe4, 0xe4, 0xf8, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc,
0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xf8, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc,
0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xf8, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc,
0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xe8, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xfc, 0xe8, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc,
0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xe8, 0xe4, 0xe4, 0xe4, 0xe8, 0xf8, 0xfc, 0xfc, 0xfc, 0xfc, 0xe8, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc,
};
i=0; // counter
for(r=0; r<32; r++) // count rows
{
for(c=0; c<32; c++) // column counter
{
pset(x+c,r+y,tweety[i]);
i++; // increment counter
}
}
}
char peek(int address) // function implementation of peek
{
return *((char *)address);
}
void poke(int address, char value) // function implementation of poke
{
*((char *)address) = value;
}
void clearscreen() // white text on dark blue background
{
int i;
for (i=0;i<40;i++)
{
t_setpos(0,0,i); // move cursor to next line
t_color(0,0x08FC); // RRGGBBxx eg dark blue background 00001000 white text 11111100
}
}
void sleep(int milliseconds) // sleep function
{
_waitcnt(_cnt()+(milliseconds*(_clockfreq()/1000))-4296);
}
void stopallcogs() // stop all cogs except the one running C
{
int i;
int c; // cog running C
c=_cogid();
for(i=0;i<8;i++)
{
if(i != c)
{
_cogstop(i); // stop this cog if not the one running C
}
}
}
void main ()
{
int i;
clearscreen();
printf("Clock speed %u \n",_clockfreq()); // see page 28 of the propeller manual for other useful commands
printf("load cogject into cog 7\n");
printf("Catalina running in cog number %i \n",_cogid()); // integer
sleep(4000); // for CRT display to warm up
stopallcogs(); // stop all cogs except C one
vga160(7); // start graphic driver in cog 7
displayclear(); // clear the display
plotbox(0,0,159,119,rgb(255,0,0)); // draw a box in red 1 pixel in from the edges
// pset(0,0,0xff); // top left corner to white
// pset(0,119,rgb(0,255,0)); // set pixel to red green blue value bottom left corner
// pset(159,0,rgb(0,0,255)); // top right corner
// pset(159,119,rgb(255,255,0)); // bottom right corner
displayicon(50,50); // display 32x32 picture
plotbox(49,49,82,82,rgb(0,255,0)); // draw a box around the picture
while (1); // Prop reboots on exit from main()
}

