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() }