Go Down

Topic: Batsocks TellyMate Shield (Read 988 times) previous topic - next topic

Mike Mc

Thought you might like to see some pics of the Batsocks TellyMate Shield hooked up to my 47" LCD TV:-








florinc

The quality is really impressive.
I am wondering if somebody already started implementing some old fashioned apps, like tennis, or even come up with a ZX Spectrum "replacement".


Mike Mc

I'm going to give 'Pong' a go for starters :)

mem

#3
May 20, 2009, 09:34 am Last Edit: May 20, 2009, 09:35 am by mem Reason: 1
Hi Mike, I starting working on that as well, how far along is yours?

Mike Mc


mem

#5
May 20, 2009, 04:34 pm Last Edit: May 20, 2009, 04:35 pm by mem Reason: 1
Here is a version of pong for the TellyMate. The gameplay is  based on some code Tom Igoe posted here: http://www.tigoe.net/pcomp/code/category/Processing/454#more-454
Code: [Select]
/*
 TellyPong
 pong for the TellyMate shield
 based on gameplay created by Tom Igoe http://www.tigoe.net/pcomp/code/category/Processing/454#more-454
 modified by mem 20 May 2009

 This example uses the TellyMate shield http://www.batsocks.co.uk/products/Other/TellyMate%20Shield.htm
*/

#define RIGHT_PIN 0  // pins connected to pots (2 and 0 are sliders 1 and 3 on dangershield)
#define LEFT_PIN  2

// define the edges of the screen:
#define HEIGHT 25
#define WIDTH  38
#define LEFT    0
#define RIGHT  (WIDTH -1)
#define TOP     0
#define BOTTOM (HEIGHT-1)

#define PADDLESIZE  1      // this how many pixels the paddle extends top and bottom  
#define SPEED    4000      // how many milliseconds it takes the ball to move across the screen

#define BALL      'o'      // character code for ball
#define PADDLE    219      // character for paddle (see http://en.wikipedia.org/wiki/Code_page_437)

#define CHAR_ESC "\x1B"    // escape character used in TellyMate commands

int ballX = WIDTH/2;          // X position of the ball
int ballY = HEIGHT/2;         // Y position of the ball
int ballDirectionY = 1;       // X direction of the ball
int ballDirectionX = 1;       // Y direction of the ball

int rightPaddleY = 0;         // X position of the center of the right paddle
int leftPaddleY = 0;          // Y position of the center of the right paddle

int prevRight = -1;           // holds previous paddle position
int prevLeft  = -1;           // set to -1 to force display on startup

long timeStamp = 0;           // time stamp to control the pauses between ball moves
long interval = SPEED/WIDTH ; // interval in milliseconds between ball moves
boolean gamePaused = false;   // state of the game

void setup() {
 Serial.begin(57600); //57k6 baud
 screen_clear();
 Serial.println("TellyPong!");
 cursor_show(false); // turn cursor off
 delay(1000);
 screen_clear();
}

void loop() {
 // read input:
 readSensors();
 // move the ball:
 if (gamePaused) {
   if (millis() - timeStamp > interval*10) {
     // if enough time has passed, start the game again:
     gamePaused = false;
   }
 }
 // if the game isn't paused, and enough time between ball moves
 // has passed, move the ball and update the timestamp:
 else {
   if (millis() - timeStamp > interval) {
     moveBall();
     timeStamp = millis();
   }
 }
}

void readSensors() {
 // read the sensors for X and Y values:
 leftPaddleY = map(analogRead(LEFT_PIN), 0, 1023, 0, BOTTOM);
 if( leftPaddleY != prevLeft){
    drawPaddle(' ',0, prevLeft); // erase old paddle
    drawPaddle(PADDLE,0, leftPaddleY);
    prevLeft = leftPaddleY;
 }
 rightPaddleY = map(analogRead(RIGHT_PIN), 0, 1023, 0, BOTTOM);
 if( rightPaddleY != prevRight){
    drawPaddle(' ',RIGHT, prevRight); // erase old paddle
    drawPaddle(PADDLE,RIGHT, rightPaddleY);
    prevRight = rightPaddleY;
 }
}

void moveBall() {
 // check to see if the ball is in the horizontal range
 // of the paddles:

 // right:
 if (ballX >= RIGHT - 1) {
   // if the ball's next Y position is between
   // the top and bottom of the paddle, reverse its  X direction:
   if ((ballY + ballDirectionY >= rightPaddleY - PADDLESIZE)
     && (ballY + ballDirectionY <= rightPaddleY + PADDLESIZE)) {
     // reverse the ball horizontal direction:
     ballDirectionX = -ballDirectionX;
   }
 }

 // left:
 if (ballX <= LEFT + 1) {
   // if the ball's next Y position is between
   // the top and bottom of the paddle, reverse its  X direction:
   if ((ballY + ballDirectionY >= leftPaddleY - PADDLESIZE )
     && (ballY + ballDirectionY <= leftPaddleY + PADDLESIZE )) {
     // reverse the ball horizontal direction:
     ballDirectionX = -ballDirectionX;  
   }
 }

 // if the ball goes off the screen bottom,
 // reverse its Y direction:
 if (ballY == BOTTOM) {
   ballDirectionY = -ballDirectionY;
 }
 // if the ball goes off the screen top,
 // reverse its X direction:
 if (ballY == TOP) {
   ballDirectionY = -ballDirectionY;
 }

 // clear the ball's previous position:
   screenShowXY(' ', ballX, ballY);

 // if the ball goes off the screen left or right:
 if ((ballX == LEFT) || (ballX == RIGHT)) {
   // reset the ball:
   ballX = WIDTH/2;
   ;
   ballY = HEIGHT/2;
   // pause  and note the time you paused:
   gamePaused = true;
   timeStamp = millis();
 }
 // increment the ball's position in both directions:
 ballX = ballX + ballDirectionX;
 ballY = ballY + ballDirectionY;
 
 // if the game isn't paused, set the ball
 // in its new position:
 if (!gamePaused) {
   // set the new position:
    screenShowXY(BALL, ballX, ballY);
 }
}

void drawPaddle(char paddleChar, int x, int y)
{
 for(int i =-PADDLESIZE; i <= PADDLESIZE; i++)
 {
   screenShowXY(paddleChar, x, y + i);
 }
}

// TellyMate helper functions

void screenShowXY( char ch, int x, int y){
 // display the given character at the screen x and y location  
 cursor_move(y,x);
 Serial.print(ch);
}
void screen_clear( void )
{ // <ESC>E
 Serial.print( CHAR_ESC "E" );
}

void cursor_move( uint8_t row , uint8_t col )
{ // <ESC>Yrc
 Serial.print( CHAR_ESC "Y" ) ;
 Serial.print((unsigned char)(32 + row)) ;
 Serial.print((unsigned char)(32 + col)) ;
}

void cursor_show( bool show )
{ // <ESC>e or <ESC>f
 Serial.print( CHAR_ESC ) ;
 Serial.print( show?'e':'f' ) ;
}

Mike Mc

Nice one. I haven't got that shield but will modify it for my kit. Thanks!

mem

Quote
I haven't got that shield but will modify it for my kit

what modificaitons ? it looks like we use the same shield.

Mike Mc

The 'dangershield' mentioned in your code.

mem

You only need to set the analog pin assignments for your pots. I am not using any of the other features of the DangerShield - but it would be cool to use the piezo to add sound for ball contacts, and perhaps use the swtiches to start and pause the game. hmmm


mem

#10
May 21, 2009, 03:41 pm Last Edit: May 21, 2009, 06:16 pm by mem Reason: 1
here a version that uses a speaker or piezo on pin 3 for sound.

Code: [Select]
/*
 TellyPong
 pong for the TellyMate shield
 based on gameplay created by Tom Igoe http://www.tigoe.net/pcomp/code/category/Processing/454#more-454
 modified by mem 20 May 2009

 This example uses the TellyMate shield http://www.batsocks.co.uk/products/Other/TellyMate%20Shield.htm
*/

#define RIGHT_PIN 0  // pins connected to pots (2 and 0 are sliders 1 and 3 on dangershield)
#define LEFT_PIN  2

#define BUZZER_PIN 3 // digital pin connected to a piezo buzzer or speaker
#define PADDLE_SOUND 2000
#define EDGE_SOUND   500

// define the edges of the screen:
#define HEIGHT 25
#define WIDTH  38
#define LEFT    0
#define RIGHT  (WIDTH -1)
#define TOP     0
#define BOTTOM (HEIGHT-1)

#define PADDLESIZE  1      // this how many pixels the paddle extends top and bottom  
#define SPEED    4000      // how many milliseconds it takes the ball to move across the screen

#define BALL      'o'      // character code for ball
#define PADDLE    219      // character for paddle (see http://en.wikipedia.org/wiki/Code_page_437)

#define CHAR_ESC "\x1B"    // escape character used in TellyMate commands

int ballX = WIDTH/2;          // X position of the ball
int ballY = HEIGHT/2;         // Y position of the ball
int ballDirectionY = 1;       // X direction of the ball
int ballDirectionX = 1;       // Y direction of the ball

int rightPaddleY = 0;         // X position of the center of the right paddle
int leftPaddleY = 0;          // Y position of the center of the right paddle

int prevRight = -1;           // holds previous paddle position
int prevLeft  = -1;           // set to -1 to force display on startup

long timeStamp = 0;           // time stamp to control the pauses between ball moves
long interval = SPEED/WIDTH ; // interval in milliseconds between ball moves
boolean gamePaused = false;   // state of the game

void setup() {
 pinMode(BUZZER_PIN, OUTPUT); // if using speaker
 Serial.begin(57600); //57k6 baud
 screen_clear();
 Serial.println("TellyPong!");
 cursor_show(false); // turn cursor off
 delay(1000);
 screen_clear();
}

void loop() {
 // read input:
 readSensors();
 // move the ball:
 if (gamePaused) {
   if (millis() - timeStamp > interval*10) {
     // if enough time has passed, start the game again:
     gamePaused = false;
   }
 }
 // if the game isn't paused, and enough time between ball moves
 // has passed, move the ball and update the timestamp:
 else {
   if (millis() - timeStamp > interval) {
     moveBall();
     timeStamp = millis();
   }
 }
}

void readSensors() {
 // read the sensors for X and Y values:
 leftPaddleY = map(analogRead(LEFT_PIN), 0, 1023, 0, BOTTOM);
 if( leftPaddleY != prevLeft){
    drawPaddle(' ',0, prevLeft); // erase old paddle
    drawPaddle(PADDLE,0, leftPaddleY);
    prevLeft = leftPaddleY;
 }
 rightPaddleY = map(analogRead(RIGHT_PIN), 0, 1023, 0, BOTTOM);
 if( rightPaddleY != prevRight){
    drawPaddle(' ',RIGHT, prevRight); // erase old paddle
    drawPaddle(PADDLE,RIGHT, rightPaddleY);
    prevRight = rightPaddleY;
 }
}

void moveBall() {
 // check to see if the ball is in the horizontal range
 // of the paddles:

 // right:
 if (ballX >= RIGHT - 1) {
   // if the ball's next Y position is between
   // the top and bottom of the paddle, reverse its  X direction:
   if ((ballY + ballDirectionY >= rightPaddleY - PADDLESIZE)
     && (ballY + ballDirectionY <= rightPaddleY + PADDLESIZE)) {
     // reverse the ball horizontal direction:
     ballDirectionX = -ballDirectionX;
     playSound(PADDLE_SOUND);
   }
 }

 // left:
 if (ballX <= LEFT + 1) {
   // if the ball's next Y position is between
   // the top and bottom of the paddle, reverse its  X direction:
   if ((ballY + ballDirectionY >= leftPaddleY - PADDLESIZE )
     && (ballY + ballDirectionY <= leftPaddleY + PADDLESIZE )) {
     // reverse the ball horizontal direction:
     ballDirectionX = -ballDirectionX;  
     playSound(PADDLE_SOUND);
   }
 }

 // if the ball goes off the screen bottom,
 // reverse its Y direction:
 if (ballY == BOTTOM) {
   ballDirectionY = -ballDirectionY;
 }
 // if the ball goes off the screen top,
 // reverse its X direction:
 if (ballY == TOP) {
   ballDirectionY = -ballDirectionY;
 }

 // clear the ball's previous position:
   screenShowXY(' ', ballX, ballY);

 // if the ball goes off the screen left or right:
 if ((ballX == LEFT) || (ballX == RIGHT)) {
   playMiss();
   // reset the ball:
   ballX = WIDTH/2;
   ;
   ballY = HEIGHT/2;
   // pause  and note the time you paused:
   gamePaused = true;
   timeStamp = millis();
 }
 // increment the ball's position in both directions:
 ballX = ballX + ballDirectionX;
 ballY = ballY + ballDirectionY;
 
 // if the game isn't paused, set the ball
 // in its new position:
 if (!gamePaused) {
   // set the new position:
    screenShowXY(BALL, ballX, ballY);
 }
}

void drawPaddle(char paddleChar, int x, int y)
{
 for(int i =-PADDLESIZE; i <= PADDLESIZE; i++)
 {
   screenShowXY(paddleChar, x, y + i);
 }
}

void playSound(int period ){
 digitalWrite(BUZZER_PIN,HIGH);
 delayMicroseconds(period);
 digitalWrite(BUZZER_PIN, LOW);
 delayMicroseconds(period);
}

void playMiss(){
 for(int i=0; i < 100; i++)
    playSound(400);  
 for(int i=0; i < 100; i++)
    playSound(3000 + i);  
}

// TellyMate helper functions

void screenShowXY( char ch, int x, int y){
 // display the given character at the screen x and y location  
 cursor_move(y,x);
 Serial.print(ch);
}
void screen_clear( void )
{ // <ESC>E
 Serial.print( CHAR_ESC "E" );
}

void cursor_move( uint8_t row , uint8_t col )
{ // <ESC>Yrc
 Serial.print( CHAR_ESC "Y" ) ;
 Serial.print((unsigned char)(32 + row)) ;
 Serial.print((unsigned char)(32 + col)) ;
}

void cursor_show( bool show )
{ // <ESC>e or <ESC>f
 Serial.print( CHAR_ESC ) ;
 Serial.print( show?'e':'f' ) ;
}



Mike Mc

Nice. I'll give that a try some time this week when I get a chance.

Go Up