DCF77 clock using the HY-1.8 LCD display. Sets KL25Z RTC clock and will continue to run with no DCF signal. Import the libraries to work on FRDM-KL25Z board, sends 8 bit writes to the LCD.

Dependencies:   HY-1_8TFT_ST7735 TSI mbed

Fork of KL25Z_DCF77_HY-1_8LCD by Paul Staron

This project shows the KL25Z connected to a very cheap (3 Euros) Chinese TFT LCD Display (HY-1.8 SPI from Ebay). I have modified a ST7753 driver library to work the 8 bit SPI write that the Mbed library sets the FRDM board to (not sure why as the KL25Z MCU has16 bit cababiliy). The libraries are available for import from my home page. and includes five different fonts (three are needed for this example).

I have also used the Analog Out (pin PTE30) to control the LED back light level, simply connect a small NPN transistor in the LED -ve connection to ground and feed the analog out pin to the base of the transistor via a 10k ohm resistor. When you slide your finger across the TSI touch slider the display brightness can be changed from off to full level.

The code it much the same as the other projects I have published, just with different LCD drive code. This program will decode the DCF77 signal connected to pin PTE20 and set the RTC clock. The photo shows the display before I modified the LED backlight drive circuit.

The display runs at 5V and draws arround 20mA, the backlight led will also run at this voltage and is nice and bright. It can also be connected to the USB 3v pin and runs at a lower level. there is a solder jumper to bypass the 5v regulator, leave this open and it will run on both volages, if this jumper is closed it will bypass the regulator and if connected to the 5v supply, the display will be 'bricked' so take care!.

This display is considerably better and cheaper than the Nokia display but not as good as Oled. Easy to connect, 5 data connections and 2 power wires. It also includes a SD card slot that can be connected to the FRDM board.

The backlight is LED it does not use a switch mode DC-DC converter circuit so RF noise is very low, this is essential when using a sensitive VLF DCF77 radio receiver close by.

The FRDM board and display runs at 50mA depending on LED brightness.

/media/uploads/star297/_scaled_20130322_132442.jpg

Files at this revision

API Documentation at this revision

Comitter:
smultron1977
Date:
Mon Dec 12 21:35:42 2011 +0000
Child:
1:6f4c5876140d
Commit message:
Original 2 hour hack

Changed in this revision

RotaryEncoder.lib Show annotated file Show diff for this revision Revisions of this file
ST7735_TFT.lib Show annotated file Show diff for this revision Revisions of this file
TFT_fonts.lib Show annotated file Show diff for this revision Revisions of this file
ball.cpp Show annotated file Show diff for this revision Revisions of this file
ball.h Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed.bld Show annotated file Show diff for this revision Revisions of this file
paddle.cpp Show annotated file Show diff for this revision Revisions of this file
paddle.h Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/RotaryEncoder.lib	Mon Dec 12 21:35:42 2011 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/shintamainjp/code/RotaryEncoder/#8000eddbf4aa
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ST7735_TFT.lib	Mon Dec 12 21:35:42 2011 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/smultron1977/code/ST7735_TFT/#967235e6fd48
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/TFT_fonts.lib	Mon Dec 12 21:35:42 2011 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/dreschpe/code/TFT_fonts/#31ce4466ecdf
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ball.cpp	Mon Dec 12 21:35:42 2011 +0000
@@ -0,0 +1,100 @@
+#include "mbed.h"
+#include "ball.h"
+
+Ball::Ball() {
+  int x=y=width=height=color=xInc=yInc=0;
+}
+
+Ball::Ball(int x, int y, int w, int h, int c, int xi, int yi)
+ : x(x), y(y), width(w), height(h), color(c), xInc(xi), yInc(yi) {}
+ 
+ 
+/* 
+ * Member Function move:
+ * Description: Colors in the previous ball black
+ *  and moves ball to new position.
+ */
+void Ball::move(ST7735_TFT &lcd) {
+  draw(lcd, true);
+  x += xInc; y += yInc;
+}
+
+/* 
+ * Member Function draw:
+ * Description: Draws object on screen
+ *  if isBlack, color in black.
+ */
+void Ball::draw(ST7735_TFT &lcd, bool isBlack) const {
+  lcd.fillrect(x, y, x+width, y+height, (isBlack) ? 0x000000 : color);
+}
+
+int Ball::size() const {
+  return width*height;
+}
+
+int Ball::getX() const {
+  return x;
+}
+
+int Ball::getY() const {
+  return y;
+}
+
+bool Ball::hitX() {
+  return (x+width<=width) || (x+width>=160);
+}
+
+bool Ball::hitY() {
+  return (y<=0) || (y+height>=128);
+}
+
+/* 
+ * Member Function hitP1:
+ * Description: Checks to see if there is
+ *  a collision between paddle1 and the ball.
+ *  Has special functionality for changing
+ *  y-incline based on collision point.
+ */
+bool Ball::hitP1(int _x, int _y, int _height) {
+  bool hit = ((_x>=x) && (xInc<0)) && 
+         (((_y<=y) && (_y+_height>=y+height)) ||
+          ((_y>=y) && (_y<=y+height)) ||
+          ((_y+_height>=y) && (_y+_height<=y+height))
+         );
+  if(hit) {
+    if(_y+_height-y < 4 && yInc>0) yInc = 2;
+    if(y-_y < 4 && yInc<0) yInc = -2;
+    else yInc = (yInc>0) ? 1 : -1;
+  }
+  return hit;
+}
+
+
+/* 
+ * Member Function hitP2:
+ * Description: Checks to see if there is
+ *  a collision between paddle2 and the ball.
+ *  Has special functionality for changing
+ *  y-incline based on collision point.
+ */
+bool Ball::hitP2(int _x, int _y, int _height) {
+  bool hit = ((_x<=x+width) && (xInc>0)) && 
+         (((_y<=y) && (_y+_height>=y+height)) ||
+          ((_y>=y) && (_y<=y+height)) ||
+          ((_y+_height>=y) && (_y+_height<=y+height))
+         );
+  if(hit) {
+    if(_y+_height-y < 4 && yInc>0) yInc = 2;
+    if(y-_y < 4 && yInc<0) yInc = -2;
+    else yInc = (yInc>0) ? 1 : -1;
+  }
+  return hit;
+}
+
+void Ball::reverseX() {
+  xInc *= -1;
+}
+
+void Ball::reverseY() {
+  yInc *= -1;
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ball.h	Mon Dec 12 21:35:42 2011 +0000
@@ -0,0 +1,26 @@
+#include "ST7735_TFT.h"
+
+class Ball {
+  /* This class creates a ball object */
+  
+  // Attributes
+  int x,y,width,height,color,xInc,yInc;
+
+public:
+  // Constructors
+  Ball();
+  Ball(int x, int y, int w, int h, int c, int xi, int yi);
+  
+  // Member functions
+  void move(ST7735_TFT &lcd);
+  void draw(ST7735_TFT &lcd, bool isBlack) const;
+  int getX() const;
+  int getY() const;
+  bool hitX();
+  bool hitY();
+  bool hitP1(int _x, int _y, int _height);
+  bool hitP2(int _x, int _y, int _height);
+  int size() const;
+  void reverseX();
+  void reverseY();
+};
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Mon Dec 12 21:35:42 2011 +0000
@@ -0,0 +1,109 @@
+/** ST7735 Pong by Jonne Valola, derived work from William Johnston's mbed Pong for NokiaLCD / PS2 keyboard
+* This pong uses a rotary encoder hooked to pins 21 and 22,
+* ST7735_TFT library by me, RotaryEncoder library by Shinichiro Nakamura
+* All copyrights of respective owners. Use on your own risk and discretion.  
+*/ 
+
+#include "mbed.h"
+#include "ball.h"
+#include "paddle.h"
+#include "ST7735_TFT.h"
+#include "string"
+#include "Arial12x12.h"
+#include "Arial24x23.h"
+#include "RotaryEncoder.h"
+
+RotaryEncoder re(p21, p22, 0, 600, 300);
+
+// State enumerator
+typedef enum {
+  RESET, RUN, PAUSE
+} STATES;
+
+ST7735_TFT lcd(p5, p6, p7, p8, p11, p15,"TFT"); // mosi, miso, sclk, cs, rs, reset
+
+/* 
+ * Subroutine drawScreen:
+ * Description: Draws both paddles
+ *  and the ball.
+ */
+void drawScreen(Paddle paddle1, Paddle paddle2, Ball theBall, bool isBlack) {
+  paddle1.draw(lcd, isBlack);
+  paddle2.draw(lcd ,isBlack);
+  theBall.draw(lcd ,isBlack);
+}
+
+/* 
+ * Subroutine drawScores:
+ * Description: Draws the scoreboard
+ */
+void drawScores(Paddle paddle1, Paddle paddle2) {
+  lcd.locate(60,1);
+  lcd.printf("%d", paddle1.getScore());
+  lcd.locate(90,1);
+  lcd.printf("%d", paddle2.getScore());
+  lcd.fillrect(79,0,81,128,0xFFFFFF);
+}
+
+int main() {
+  lcd.background(0x000000);
+  lcd.cls();
+  lcd.set_orientation(1);
+  lcd.set_font((unsigned char*) Arial12x12);  // select the font
+  Paddle paddle1, paddle2;
+  Ball theBall;
+  int temp, count=0, oldY;
+  drawScreen(paddle1, paddle2, theBall, false);
+  drawScores(paddle1, paddle2);
+  STATES state = RESET; // Initial state is RESET
+  while(1) {  
+    switch(state) {
+      case RESET: // Reset objects, draw the screen, state = PAUSE
+        lcd.cls();
+        paddle1 = Paddle(0,40,5,25,0xFFFFFF,paddle1.getLives(),paddle1.getScore());
+        paddle2 = Paddle(154,40,5,25,0xFFFFFF,paddle2.getLives(),paddle2.getScore());
+        theBall = Ball(80,64,5,5,0xFFFF00,1,1);
+        drawScreen(paddle1, paddle2, theBall, false);
+        drawScores(paddle1, paddle2);
+        oldY = re.getVal();
+        state = RUN;
+        break;
+      case RUN: 
+        if (oldY > re.getVal()) { // Executes if encoder turned
+                if(paddle1.getY()>2)
+                paddle1.move(lcd, -2);
+        }
+         if (oldY < re.getVal()) { // Executes if encoder turned
+              if(paddle1.getY()+paddle1.getHeight()<128)
+                paddle1.move(lcd, 2);
+        }
+        oldY = re.getVal();
+       
+        if(count%2) // Only let CPU move once every 2 times through the loop
+          paddle2.moveCPU(lcd, theBall.getY());
+        if(++count==5) { // Only move the ball once every 5 times through the loop
+          count = 0;
+          if(theBall.hitP1((paddle1.getX()+paddle1.getWidth()), paddle1.getY(), paddle1.getHeight()))
+            theBall.reverseX();
+          if(theBall.hitP2(paddle2.getX(), paddle2.getY(), paddle2.getHeight()))
+            theBall.reverseX();
+          if(theBall.hitX()) { // If the ball hits one of the sides of the screen
+            if(theBall.getX()<7) { // If the ball hit paddle1's side
+                paddle2.addPoint();              
+            }
+            else if(theBall.getX()>153) { // If the ball hit paddle2's side
+                paddle1.addPoint();            
+            }
+            theBall.reverseX();
+            state = RESET; // Reset the objects
+          }
+          if(theBall.hitY()) 
+            theBall.reverseY();
+          theBall.move(lcd);
+        }
+        break;
+    }
+    drawScreen(paddle1, paddle2, theBall, false);
+    drawScores(paddle1, paddle2);
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed.bld	Mon Dec 12 21:35:42 2011 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/mbed/builds/029aa53d7323
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/paddle.cpp	Mon Dec 12 21:35:42 2011 +0000
@@ -0,0 +1,80 @@
+#include "mbed.h"
+#include "paddle.h"
+
+Paddle::Paddle() {
+  int x=y=width=height=color=score=0;
+  lives = 3;
+}
+
+Paddle::Paddle(int x, int y, int w, int h, int c, int l, int s)
+ : x(x), y(y), width(w), height(h), color(c), lives(l), score(s) {}
+ 
+/* 
+ * Member Function move:
+ * Description: Colors in the previous paddle black
+ *  and moves paddle to new position.
+ */
+void Paddle::move(ST7735_TFT &lcd, int increment) {
+  draw(lcd, true);
+  y += increment;
+}
+
+
+/* 
+ * Member Function moveCPU:
+ * Description: Colors in the previous paddle black
+ *  and moves paddle to new position.
+ *  inc variable allows paddle to only move every
+ *  other function call.
+ */
+void Paddle::moveCPU(ST7735_TFT &lcd, int _y) {
+  static int inc = 1;
+  draw(lcd, true);
+  if(_y>y+height/2 && y+height<128) y += inc;
+  else if(_y+5<y+height/2 && y>0) y -= inc;
+  inc = (inc) ? 0 : 1;
+}
+
+void Paddle::draw(ST7735_TFT &lcd, bool isBlack) const {
+  lcd.fillrect(x, y, x + width, y + height, (isBlack) ? 0x000000 : color);
+}
+
+bool Paddle::loseLife() {
+  return --lives;
+}
+
+void Paddle::addPoint() {
+  ++score;
+}
+
+int Paddle::size() const {
+  return width*height;
+}
+
+int Paddle::getWidth() const {
+  return width;
+}
+
+int Paddle::getHeight() const {
+  return height;
+}
+
+int Paddle::getX() const {
+  return x;
+}
+
+int Paddle::getY() const {
+  return y;
+}
+
+int Paddle::getLives() const {
+  return lives;
+}
+
+int Paddle::getScore() const {
+  return score;
+}
+
+void Paddle::setLives(int l) {
+  lives = l;
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/paddle.h	Mon Dec 12 21:35:42 2011 +0000
@@ -0,0 +1,29 @@
+#include "ST7735_TFT.h"
+
+class Paddle {
+  /* This class creates a paddle object */
+ 
+  // Attributes
+  int x,y,width,height,color,lives,score;
+
+public: 
+  // Constructors
+  Paddle();
+  Paddle(int x, int y, int w, int h, int c, int l, int s);
+  
+  // Member functions
+  void move(ST7735_TFT &lcd, int increment);
+  void moveCPU(ST7735_TFT &lcd, int _y);
+  void draw(ST7735_TFT &lcd, bool isBlack) const;
+  bool loseLife();
+  void addPoint();
+  int size() const;
+  int getWidth() const;
+  int getHeight() const;
+  int getX() const;
+  int getY() const;
+  int getLives() const;
+  int getScore() const;
+  void setLives(int l);
+  
+};
\ No newline at end of file