/* Copyright (c) 2009, Keith Batten. Contactable at @batsocks.co.uk Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. Disclaimer This software is provided 'as is' without warranty of any kind. This software may not meet your requirements or expectations. This software may include mistakes, errors and inaccuracies. The copyright holder will not be liable for any damages arising from your use, or misuse, of this software. Use at your own risk. */ /* Batsocks Paint ============== A simple character-based 'painting' application for the Arduino with a TellyMate Shield. Input: ====== 6 buttons arranged as left/right/up/down and paint/shift The pin assignments for the 6 buttons were designed for use with the Batsocks 6 button shield, but can easily be adapted for use with buttons on other pins. Pins: Up, Down, Left, Right : D6, D3, D4, D5 Paint , Shift : D7, D2 The buttons are normally open and connect to ground when closed. Output: ======= Serial data is sent to the TellyMate shield on D1 (TX). The TellyMate Shield shows the results on a PAL or NTSC TV. Instructions: ============= Instructions are shown in the print_instructions function. Other documentation: ==================== For documentation on all the control sequences that the TellyMate can use, please see... http://www.batsocks.co.uk/products/Other/TellyMate_UserGuide.htm */ // Useful character constant macros... #define CHAR_ESC "\x1B" #define CHAR_DLE "\x10" // global variables/constants char brush = 'A' ; // current brush character const char brush_max = 255 ; const char brush_min = 32 ; void setup() { // init buttons pinMode( 2, INPUT ) ; // Set the buttons to input pinMode( 3, INPUT ) ; pinMode( 4, INPUT ) ; pinMode( 5, INPUT ) ; pinMode( 6, INPUT ) ; pinMode( 7, INPUT ) ; digitalWrite( 2, HIGH ) ; // Turn on the buttons' internal pull-up resistors digitalWrite( 3, HIGH ) ; digitalWrite( 4, HIGH ) ; digitalWrite( 5, HIGH ) ; digitalWrite( 6, HIGH ) ; digitalWrite( 7, HIGH ) ; // init TellyMate display Serial.begin(57600); //57k6 baud Serial.print( CHAR_ESC "E" ); // clear screen Serial.print( CHAR_ESC "f" ); // hide cursor print_instructions() ; while ( ( digitalRead( 2 ) & digitalRead( 3 ) & digitalRead( 4 ) & digitalRead( 5 ) & digitalRead( 6 ) & digitalRead( 7 ) ) != LOW ) {} // wait until any button is pressed Serial.print( CHAR_ESC "E" ); // clear screen Serial.print( CHAR_ESC "Y" ) ; // move the cursor Serial.print((unsigned char)(32 + 10)) ; //start at row 10 Serial.print((unsigned char)(32 + 15)) ; //start at column 15 Serial.print( CHAR_ESC "e" ); // show cursor Serial.print( CHAR_ESC "x" "4" ); // block cursor } void loop() { // draw the brush at the top left of the screen Serial.print( CHAR_ESC "j" ) ; //save the cursor position Serial.print( CHAR_ESC "H" ) ; //move the cursor to Home Serial.print( brush ) ; Serial.print( CHAR_ESC "k" ) ; //restore the previous cursor position if (digitalRead( 2 ) == LOW) { // SHIFT button pressed if (digitalRead( 7 ) == LOW) { // SHIFT and DRAW buttons pressed, so print a space character Serial.print( CHAR_ESC "j" ) ; //save the cursor position Serial.print( ' ' ) ; //print a space Serial.print( CHAR_ESC "k" ) ; //restore the previous cursor position } if (digitalRead( 6 ) == LOW) { // SHIFT and UP buttons pressed, so increase brush character if ( brush == brush_max ) { // can't increment any further, so start with the first character again. brush = brush_min ; } else { // increment brush character brush += 1 ; } } if (digitalRead( 3 ) == LOW) { // SHIFT and DOWN buttons pressed, so decrease brush character // checks if brush is at the minimum and sets it to the maximum, otherwise decrements it. if ( brush == brush_min ) { // can't decrement any further, so go to the last character brush = brush_max ; } else { // decrement brush character brush -= 1 ; } } } else { // SHIFT button NOT pressed if (digitalRead( 7 ) == LOW) { // DRAW pressed so print the brush character Serial.print( CHAR_ESC "j" ) ; //save the cursor position Serial.print( brush ) ; Serial.print( CHAR_ESC "k" ) ; //restore the previous cursor position } if (digitalRead( 3 ) == LOW) { // DOWN pressed, so move the cursor down Serial.print( CHAR_ESC "B" ) ; //cursor down } if (digitalRead( 4 ) == LOW) { // LEFT pressed, so move the cursor left Serial.print( CHAR_ESC "D" ) ; //cursor left } if (digitalRead( 5 ) == LOW) { // RIGHT button pressed, so move the cursor right Serial.print( CHAR_ESC "C" ) ; //cursor right } if (digitalRead( 6 ) == LOW) { // UP button pressed, so move the cursor up Serial.print( CHAR_ESC "A" ) ; // cursor up } } delay( 100 ) ; // steady now, not too fast... } void print_instructions() { Serial.print( CHAR_ESC "_4") ; // Large text, top half Serial.println(" Batsocks Paint") ; Serial.print( CHAR_ESC "_5") ; // Large text, bottom half Serial.println(" Batsocks Paint") ; Serial.println(" For the TellyMate Shield" ) ; Serial.println(""); Serial.println(""); Serial.println(" Pin assignments (for buttons to GND)"); Serial.println(""); // printing the direction arrows: // The direction arrows are in the lower 31 characters of code page 437. // If they are output to the TellyMate directly, they are interpreted as // control codes, however if they are prefixed by , the TellyMate // knows to treat them as normal characters. Serial.println( " 6") ; Serial.println( " 7 (Paint)" ); Serial.println( " 4 5" ); Serial.println( " 2 (Shift)" ) ; Serial.println( " 3" ) ; // now to print the arrows... screen_setchar( 8, 10, 0x1E ) ; // up arrow screen_setchar( 9, 9, 0x11 ) ; // left arrow screen_setchar( 9, 11, 0x10 ) ; // right arrow screen_setchar( 10, 10, 0x1F ) ; // down arrow screen_setchar( 14, 0 , ' ') ; // move the cursor to row 15. Serial.println(); Serial.println(" Cursor Keys : Move Around"); Serial.println(" Paint Key : Paints at cursor"); Serial.println(" Shift + Up : Next brush"); Serial.println(" Shift + Down : Previous Brush"); Serial.println(" Shift + Paint: Clear under cursor"); Serial.println(""); Serial.println(""); Serial.println(""); Serial.print(" Press any key to start..."); } // put the given character, c, at (row,column) void screen_setchar( byte row , byte column, byte c ) { // Y = move the cursor to row/column Serial.print( CHAR_ESC "Y" ) ; Serial.print( (unsigned char)(32 + row )) ; Serial.print( (unsigned char)(32 + column )) ; // handle the printing of control characters (e.g. <32) properly (i.e. prefix with ) if ( c < 32 ) Serial.print( CHAR_DLE ) ; // finally print the character! Serial.print( c ) ; }