Răsfoiți Sursa

First commit

01010101 12 ani în urmă
părinte
comite
615fd804ad
3 a modificat fișierele cu 1115 adăugiri și 0 ștergeri
  1. 554 0
      Minitel.cpp
  2. 209 0
      Minitel.h
  3. 352 0
      MinitelDemo/MinitelDemo.ino

+ 554 - 0
Minitel.cpp

@@ -0,0 +1,554 @@
+/**
+ * Minitel library for Arduino (v0.1) / May 2013
+ * http://github.com/01010101/Minitel
+ *
+ * By Jerome Saint-Clair aka 01010101
+ * http://saint-clair.net
+ * 
+ * For the Graffiti Research Lab France
+ * http://graffitiresearchlab.fr
+ * 
+ * Based on works from the Tetalab (Fabrice, Renaud, PG & Phil)
+ * http://tetalab.org
+ */
+ 
+ #include "Arduino.h"
+#include "SoftwareSerial.h"
+#include "Minitel.h"
+
+byte _currentBgColor = BLACK;
+byte _currentTextColor = WHITE;
+byte _currentMode = TEXT_MODE;
+byte _currentVideo = VIDEO_STANDARD;
+byte _currentSize = SIZE_NORMAL;
+boolean _currentUnderline = false;
+boolean _currentBlink = false;
+boolean _currentShowCursor = false;
+
+
+Minitel::Minitel() : SoftwareSerial(6,7) {
+	pinMode(6, OUTPUT);
+	pinMode(7, OUTPUT);
+	init();
+}
+
+
+Minitel::Minitel(int rx, int tx) : SoftwareSerial(rx,tx) {
+	pinMode(rx, INPUT);
+	pinMode(tx, OUTPUT);
+	init();
+}
+
+void Minitel::init() {
+	//Serial.begin(1200);
+	begin(1200);
+	refreshSettings();
+}
+
+byte Minitel::getGraphicChar(String s) {
+  byte carac= 32; // caractère pixel
+
+  if (s.length() == 6) {
+    carac += s[0] == '0' ? 0 : 1;
+    carac += s[1] == '0' ? 0 : 2;
+    carac += s[2] == '0' ? 0 : 4;
+    carac += s[3] == '0' ? 0 : 8;
+    carac += s[4] == '0' ? 0 : 16;
+    carac += s[5] == '0' ? 0 : 32;
+    return carac;
+  }
+  return 9;
+
+
+}
+
+void Minitel::serialprint7(byte b) {
+  boolean  i = false;
+  for(int j = 0; j<8;j++) {
+    if (bitRead(b,j)==1) {
+      i =!i; //calcul de la parité
+    }
+  }
+  if (i) {
+    bitWrite(b,7,1); //ecriture de la partié
+  }
+  else {
+    bitWrite(b,7,0); //ecriture de la partié
+  }
+  write(b); //ecriture du byte sur le software serial
+}
+
+
+
+void Minitel::graphic(String s, int x, int y){
+  moveCursorTo(x, y);
+  graphic(s); 
+}
+
+void Minitel::graphic(String s) {
+  serialprint7(getGraphicChar(s)); 
+}
+
+void Minitel::textByte(byte c) {
+  serialprint7(c);
+}
+
+void Minitel::textByte(byte b, int x, int y) {
+  moveCursorTo(x, y);
+  textByte(b);  
+}
+
+
+boolean Minitel::textChar(byte c) {
+  byte charByte = getCharByte(c);
+  if (isValidChar(charByte)) {
+    serialprint7(charByte);
+    return true;
+  }
+  return false;
+}
+
+boolean Minitel::textChar(byte c, int x, int y) {
+  moveCursorTo(x, y);
+  return textChar(c);  
+}
+
+
+void Minitel::text(String s, int x, int y) {
+  text(s, x, y, HORIZONTAL); 
+}
+
+
+void Minitel::text(String s) {
+  text(s, HORIZONTAL);
+}
+
+
+void Minitel::text(String s, int x, int y, int orientation) {
+  moveCursorTo(x, y);
+  text(s, orientation);
+}
+
+void Minitel::text(String s, int orientation) {
+  for (int i=0; i<s.length(); i++) {
+    char c = s.charAt(i);
+    boolean indent = false;
+    if (isAccent(c)) {
+      i+=1; // chars with accents take 2 array indexes
+      c = s.charAt(i);
+      indent = printAccentChar(c);
+    }
+    else {
+      indent = textChar(c);
+    }
+    if (indent && orientation == VERTICAL) {
+      moveCursor(LEFT);
+      moveCursor(DOWN);
+    }
+  }
+}
+
+
+// Characters
+/*
+ String chars0 = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; // 0 -> 33
+ String chars1= "!\"#$%&'()*+,-./0123456789:;<=>?@"; // 33 -> 64
+ String chars2 = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; // 65 -> 90
+ String chars3 = "abcdefghijklmnopqrstuvwxyz"; // 97 -> 122
+*/
+byte Minitel::getCharByte(char c) {
+  String characters = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]x_xabcdefghijklmnopqrstuvwxyz";
+  return (byte) characters.lastIndexOf(c);
+}
+
+void Minitel::specialChar(byte c, int x, int y) {
+  moveCursorTo(x, y);
+  specialChar(c);
+}
+
+void Minitel::specialChar(byte c) {
+  if (c == SPE_CHAR_BOOK || c == SPE_CHAR_PARAGRAPH
+    || c == SPE_CHAR_ARROW_LEFT || c == SPE_CHAR_ARROW_UP
+    || c == SPE_CHAR_ARROW_RIGHT || c == SPE_CHAR_ARROW_DOWN 
+    || c == SPE_CHAR_CIRCLE || c == SPE_CHAR_MINUS_PLUS
+    || c == SPE_CHAR_1_4 || c == SPE_CHAR_1_2
+    || c == SPE_CHAR_3_4 || c == SPE_CHAR_UPPER_OE
+    || c == SPE_CHAR_LOWER_OE || c == SPE_CHAR_BETA) {
+    serialprint7(25);
+    serialprint7(c);
+  }
+}
+
+
+
+boolean Minitel::isValidChar(byte index) {
+  if (index >= 32 && index < 123) {
+    return true; 
+  }
+  return false;
+}
+
+
+boolean Minitel::isAccent(char c) {
+  String accents = "áàâäéèëêíìîïóòôöúùûü";
+  if (accents.indexOf(c) >=0) {
+    return true; 
+  }
+  return false;
+}
+
+
+boolean Minitel::printAccentChar(char c) {
+  if (isAccent(c)) {
+	String accents = "áàâäéèëêíìîïóòôöúùûü";
+    int index = (accents.indexOf(c)-1)/2;
+
+    int accentTypeIndex = index%4;
+    printAccent(accentTypeIndex);
+
+    int letterIndex = floor(index/4);
+    char letter = getAccentLetter(letterIndex);
+    textChar(letter);
+
+    return true;
+  }
+  return false;
+}
+
+void Minitel::printAccent(int index) {
+  serialprint7(25);
+  switch(index) {
+    case(0) :
+    serialprint7(GRAVE);
+    break; 
+    case(1) :
+    serialprint7(ACCUTE);
+    break; 
+    case(2) :
+    serialprint7(CIRCUMFLEX);
+    break; 
+  default :
+    serialprint7(UMLAUT);
+  }
+}
+
+char Minitel::getAccentLetter(int letterIndex) {
+  switch(letterIndex) {
+    case(0) :
+    return('a');
+    break; 
+    case(1) :
+    return('e');
+    break; 
+    case(2) :
+    return('i');
+    break; 
+    case(3) :
+    return('o');
+    break;
+  default :
+    return('u');
+  }  
+}
+
+void Minitel::repeat(byte n) {
+  serialprint7(18);
+  serialprint7(64+n);
+}
+
+
+void Minitel::bgColor(byte c) {
+  if (c >= 0 && c <=7) {
+    serialprint7(27);
+    serialprint7(c+80);
+    _currentBgColor = c;
+  }
+}
+
+
+void Minitel::textColor(byte c) {
+  if (c >= 0 && c <=7) {
+    serialprint7(27);
+    serialprint7(c+64);
+    _currentTextColor = c;
+  }
+}
+
+
+void Minitel::useDefaultColors() {
+  bgColor(BLACK);
+  textColor(WHITE); 
+}
+
+
+void Minitel::moveCursorTo(int x, int y) {
+  serialprint7(31); // Code positionnement de curseur
+  serialprint7(64+y); // coordonnées x (x+64) (x de 1 à 40)
+  serialprint7(64+x); // coordonnées y (y+64) (y de 1 à 24)
+  refreshSettings();
+}
+
+
+void Minitel::moveCursor(byte dir) {
+  if (dir == LEFT || dir == RIGHT || dir == UP || dir == DOWN) {
+    serialprint7(dir);
+  }
+}
+
+
+void Minitel::moveCursorTo(byte location) {
+  if (location == HOME || location == LINE_END || location == TOP_LEFT) {
+    serialprint7(location);
+  }
+  else if (location == CENTER || location == TOP_RIGHT || location == BOTTOM_RIGHT || location == BOTTOM_LEFT) {
+    if (location == CENTER) {
+      moveCursorTo(20, 12);
+    }
+    else if (location == TOP_RIGHT) {
+      moveCursorTo(40, 1);
+    }
+    else if (location == BOTTOM_RIGHT) {
+      moveCursorTo(40, 24);
+    }
+    else if (location == BOTTOM_LEFT) {
+      moveCursorTo(1, 24);
+    }
+    refreshSettings()  ;
+  }
+}
+
+
+void Minitel::moveCursor(byte dir, int n) {
+  if (dir == LEFT || dir == RIGHT || dir == UP || dir == DOWN) {
+    for (int i=0; i<n; i++) {
+      serialprint7(dir);
+    }
+  }
+}
+
+
+void Minitel::refreshSettings() {
+  // Common parameters
+  mode(_currentMode);
+  textColor(_currentTextColor);
+  bgColor(_currentBgColor); // Only in graphic mode ?
+  blink(_currentBlink);
+  cursor(_currentShowCursor);
+  // Graphic mode specific parameters
+  if (_currentMode == GRAPHIC_MODE) {
+    pixelate(_currentUnderline);
+  }
+  // Text mode specific parameters
+  if (_currentMode == TEXT_MODE) {
+    video(_currentVideo);
+    charSize(_currentSize);
+  }
+}
+
+
+void Minitel::cursor() {
+  cursor(true); 
+}
+
+void Minitel::noCursor() {
+  cursor(false); 
+}
+
+void Minitel::cursor(boolean b) {
+  if(b) {
+    serialprint7(CURSOR_SHOW);
+  }
+  else {
+    serialprint7(CURSOR_HIDE);
+  }
+  _currentShowCursor = b;
+}
+
+
+void Minitel::clearScreen() {
+  serialprint7(CLEARSCREEN);
+}
+
+
+void Minitel::mode(byte mode) {
+  if (mode == GRAPHIC_MODE || mode == TEXT_MODE) {
+    serialprint7(mode);
+    _currentMode = mode;
+  } 
+}
+
+void Minitel::graphicMode() {
+  mode(GRAPHIC_MODE); 
+}
+
+void Minitel::textMode() {
+  mode(TEXT_MODE); 
+}
+
+
+void Minitel::blink() {
+  blink(true); 
+}
+
+void Minitel::noBlink() {
+  blink(false); 
+}
+
+
+void Minitel::blink(boolean b) {
+  serialprint7(27);
+  if (b) {
+    serialprint7(BLINK_ON); 
+  }
+  else {
+    serialprint7(BLINK_OFF);
+  }
+  _currentBlink = b;
+}
+
+
+void Minitel::charSize(byte type) {
+  if (type == SIZE_NORMAL || type == SIZE_DOUBLE_HEIGHT || type == SIZE_DOUBLE_WIDTH || type == SIZE_DOUBLE) {
+    serialprint7(27);
+    serialprint7(type);
+    _currentSize = type;
+  }
+}
+
+
+void Minitel::incrustation(boolean b) {
+  serialprint7(27);
+  if (b) {
+    serialprint7(INCRUSTATION_ON);
+  }
+  else {
+    serialprint7(INCRUSTATION_OFF);
+  } 
+}
+
+void Minitel::pixelate() {
+  pixelate(true); 
+}
+
+void Minitel::noPixelate() {
+  pixelate(false); 
+}
+
+
+void Minitel::pixelate(boolean b) {
+  serialprint7(27);
+  if (b) {
+    serialprint7(UNDERLINE_ON);
+  }
+  else {
+    serialprint7(UNDERLINE_OFF);
+  } 
+  _currentUnderline = b;
+}
+
+
+void Minitel::setLineMask(boolean b) {
+  serialprint7(27);
+  if (b) {
+    serialprint7(LINE_MASK_ON);
+  }
+  else {
+    serialprint7(LINE_MASK_OFF);
+  } 
+}
+
+
+void Minitel::video(byte v) {
+  if (v == VIDEO_INVERT || v == VIDEO_STANDARD || v == VIDEO_TRANSPARENT) {
+    serialprint7(27);
+    serialprint7(v);
+    _currentVideo = v;
+  } 
+}
+
+void Minitel::standardVideo() {
+  video(VIDEO_STANDARD); 
+}
+
+void Minitel::invertVideo() {
+  video(VIDEO_INVERT); 
+}
+
+void Minitel::transparentVideo() {
+  video(VIDEO_TRANSPARENT); 
+}
+
+
+void Minitel::setMaxSpeed() {
+  /*
+  serialprint7(27);
+   serialprint7(SPEED_4800);
+   */
+}
+
+// Bip
+// Less than 200ms isn't taken into account
+void Minitel::bip(long duration) {
+  long beginTime = millis();
+  while(millis() < beginTime+100) {//duration) {
+    serialprint7(27);
+    serialprint7(BIP);
+    delay(100);
+  }
+}
+
+
+void Minitel::rect(char c, int x, int y, int w, int h) {
+  byte b = getCharByte(c);
+  rect(b, x, y, w, h);
+}
+
+void Minitel::rect(byte c, int x, int y, int w, int h) {
+  moveCursorTo(x, y); 
+  textByte(c);
+  repeat(w);
+  moveCursorTo(x, y+1);
+  for (int i=0; i<h-2; i++) {
+    textByte(c);
+    moveCursor(DOWN);
+    moveCursor(LEFT); 
+  }
+  moveCursorTo(x+w, y+1);
+  for (int i=0; i<h-2; i++) {
+    textByte(c);
+    moveCursor(DOWN);
+    moveCursor(LEFT); 
+  }
+  moveCursorTo(x, y+h-1);
+  textByte(c);
+  repeat(w);  
+}
+
+void Minitel::spiral(int x, int y, int siz, int c) {
+  int curSiz = 1;
+  // Center
+  specialChar(x, y, c);
+  x++;
+  // Spiral    
+  for (int i=0; i< siz; i++) {
+    for (int j=0; j<curSiz; j++) {
+      specialChar(x, y, c);
+      y++;
+    }
+    curSiz++;
+    for (int j=0; j<curSiz; j++) {
+      specialChar(x, y, c);
+      x--;
+    }
+    for (int j=0; j<curSiz; j++) {
+      specialChar(x, y, c);
+      y--;
+    }
+    curSiz++;   
+    for (int j=0; j<curSiz; j++) {
+      specialChar(x, y, c);
+      x++;
+    }    
+  }
+}
+

+ 209 - 0
Minitel.h

@@ -0,0 +1,209 @@
+/**
+ * Minitel library for Arduino (v0.1) / May 2013
+ * http://github.com/01010101/Minitel
+ *
+ * By Jerome Saint-Clair aka 01010101
+ * http://saint-clair.net
+ * 
+ * For the Graffiti Research Lab France
+ * http://graffitiresearchlab.fr
+ * 
+ * Based on works by the Tetalab (Fabrice, Renaud, PG & Phil)
+ * http://tetalab.org
+ */
+
+#ifndef Minitel_h
+#define Minitel_h
+
+#include "Arduino.h"
+#include "SoftwareSerial.h"
+
+// Modes
+
+#define GRAPHIC_MODE 14
+#define TEXT_MODE 15
+
+#define HORIZONTAL 0
+#define VERTICAL 1
+
+// Cursor moves
+#define LEFT 8
+#define RIGHT 9
+#define DOWN 10
+#define UP 11
+
+// Cursor positionning
+#define HOME 13
+#define LINE_END 24
+
+#define TOP_LEFT 30
+#define TOP_RIGHT 1001
+#define BOTTOM_LEFT 1002
+#define BOTTOM_RIGHT 1003
+#define CENTER 1004
+
+// Cursor visibility
+// Preceeded by 27
+#define CURSOR_SHOW 17
+#define CURSOR_HIDE 20
+
+// Clear screen
+#define CLEARSCREEN 12
+
+// Font type
+// Preceeded by 27
+// DOUBLE-HEIGHT and DOUBLE may not work on certain Minitels
+#define SIZE_NORMAL 76
+#define SIZE_DOUBLE_HEIGHT 77
+#define SIZE_DOUBLE_WIDTH 78
+#define SIZE_DOUBLE 79
+
+
+// Colors (+80 for background, +64 for text)
+// Preceeded by 27
+// 64->71 txt color black, red, green, yellow, blue, magenta, cyan, white
+// 80->87 bg color black, red, green, yellow, blue, magenta, cyan, white
+#define BLACK 0
+#define RED 1
+#define GREEN 2
+#define YELLOW 3
+#define MAGENTA 4
+#define BLUE 5
+#define CYAN 6
+#define WHITE 7
+
+// Blink
+// Preceeded by 27
+#define BLINK_ON 72
+#define BLINK_OFF 73
+
+// Incrustation
+// Preceeded by 27
+#define INCRUSTATION_ON 75
+#define INCRUSTATION_OFF 74
+
+// Underline
+#define UNDERLINE_ON 90
+#define UNDERLINE_OFF 89
+
+// Underline
+#define LINE_MASK_ON 88
+#define LINE_MASK_OFF 95
+
+// Video mode
+#define VIDEO_INVERT 93
+#define VIDEO_STANDARD 92
+#define VIDEO_TRANSPARENT 94
+
+// Speeds
+#define SPEED_75 0
+#define SPEED_300 1
+#define SPEED_4800 100
+#define SPEED_9600 111 // ??? Minitel 2 ???
+
+// Bip
+#define BIP 7
+
+// Accents
+#define ACCUTE 65
+#define GRAVE 66
+#define CIRCUMFLEX 67
+#define UMLAUT 72
+
+#define SUB_ARTICLE_SEPARATOR 31;
+
+// Preceeded by 25
+#define SPE_CHAR_BOOK 35
+#define SPE_CHAR_PARAGRAPH 39
+#define SPE_CHAR_ARROW_LEFT 44
+#define SPE_CHAR_ARROW_UP 45
+#define SPE_CHAR_ARROW_RIGHT 46
+#define SPE_CHAR_ARROW_DOWN 47
+#define SPE_CHAR_CIRCLE 48
+#define SPE_CHAR_MINUS_PLUS 49
+#define SPE_CHAR_1_4 60
+#define SPE_CHAR_1_2 61
+#define SPE_CHAR_3_4 62
+#define SPE_CHAR_UPPER_OE 106
+#define SPE_CHAR_LOWER_OE 122
+#define SPE_CHAR_BETA 123
+
+
+class Minitel : public SoftwareSerial {
+
+private :	
+	//String _characters;
+	//String _accents;
+	byte _currentBgColor;
+	byte _currentTextColor;
+	byte _currentMode;
+	byte _currentVideo;
+	byte _currentSize;
+	boolean _currentUnderline;
+	boolean _currentBlink;
+	boolean _currentShowCursor;
+	void init();
+	boolean isValidChar(byte index);
+	boolean isAccent(char c);
+	boolean printAccentChar(char c);
+	void printAccent(int index);
+	char getAccentLetter(int letterIndex);
+
+
+public :
+
+	Minitel();
+	Minitel(int rx, int tx);
+	void refreshSettings();
+	byte getGraphicChar(String s);
+	void serialprint7(byte b);
+	void graphic(String s, int x, int y);
+	void graphic(String s);
+	void textByte(byte c);
+	void textByte(byte b, int x, int y);
+	boolean textChar(byte c);
+	boolean textChar(byte c, int x, int y);
+	void text(String s, int x, int y);
+	void text(String s);
+	void text(String s, int x, int y, int orientation);
+	void text(String s, int orientation);
+	byte getCharByte(char c);
+	void specialChar(byte c, int x, int y);
+	void specialChar(byte c);
+	void repeat(byte n);
+	void bgColor(byte c);
+	void textColor(byte c);
+	void useDefaultColors();
+	void moveCursorTo(int x, int y);
+	void moveCursor(byte dir);
+	void moveCursorTo(byte location);
+	void moveCursor(byte dir, int n);
+	void cursor();
+	void noCursor();
+	void cursor(boolean b);
+	void clearScreen();
+	void mode(byte mode);
+	void graphicMode();
+	void textMode();
+	void blink();
+	void noBlink();
+	void blink(boolean b);
+	void charSize(byte type);
+	void incrustation(boolean b);
+	void pixelate();
+	void noPixelate();
+	void pixelate(boolean b);
+	void setLineMask(boolean b);
+	void video(byte v);
+	void standardVideo();
+	void invertVideo();
+	void transparentVideo();
+	void setMaxSpeed();
+	void bip(long duration);
+	void rect(char c, int x, int y, int w, int h);
+	void rect(byte c, int x, int y, int w, int h);
+	void spiral(int x, int y, int siz, int c);
+
+};
+
+#endif

+ 352 - 0
MinitelDemo/MinitelDemo.ino

@@ -0,0 +1,352 @@
+/**
+ * Minitel library for Arduino (v0.1) / May 2013
+ * http://github.com/01010101/Minitel
+ *
+ * By Jerome Saint-Clair aka 01010101
+ * http://saint-clair.net
+ * 
+ * For the Graffiti Research Lab France
+ * http://graffitiresearchlab.fr
+ * 
+ * Based on works by the Tetalab (Fabrice, Renaud, PG & Phil)
+ * http://tetalab.org
+ */
+
+
+#include <SoftwareSerial.h>
+#include <Minitel.h>
+
+Minitel m(6,7);
+
+void setup() {
+  
+}
+
+void loop() {
+ 
+  long pause = 2000;
+
+  demoColor();
+  delay(pause);
+
+  demoGraphics(true);
+  delay(pause);
+
+  demoGraphics(false);
+  delay(pause);
+
+  demoBip();
+  delay(pause);
+
+  demoCursor();
+  delay(pause);
+
+  demoText();
+  delay(pause);
+
+  demoCharacters();
+  delay(pause);
+  
+}
+
+/**
+ *
+ * DEMOS
+ *
+ */
+
+// Graphic characters
+
+void demoGraphics(boolean underline) {
+
+  m.clearScreen();
+  m.mode(TEXT_MODE);
+  m.textColor(WHITE);
+  m.bgColor(RED);
+  m.text(" GRAPHICS DEMO ", 4, 1);
+  m.bgColor(BLACK);
+
+  
+  m.graphicMode();
+  
+  m.pixelate(underline);
+  m.noCursor();
+
+  // No color 
+  m.useDefaultColors();
+
+  int xPos = 5;
+  int yPos = 5;
+  m.moveCursorTo(xPos, yPos);
+  int x = 32;
+  for (int i=x; i<x+16; i++) {
+    m.serialprint7(i);
+    m.serialprint7(9);
+  }
+
+  m.moveCursorTo(xPos, yPos+2);
+  for (int i=x+16; i<x+32; i++) {
+    m.serialprint7(i);
+    m.serialprint7(9);
+  }
+
+  m.moveCursorTo(xPos, yPos+4);
+  for (int i=x+32; i<x+48; i++) {
+    m.serialprint7(i);
+    m.serialprint7(9);
+  }
+
+  m.moveCursorTo(xPos, yPos+6);
+  for (int i=x+48; i<x+64; i++) {
+    m.serialprint7(i);
+    m.serialprint7(9);
+  } 
+
+  // Colored
+  m.bgColor(RED);
+  m.textColor(WHITE);
+
+  m.moveCursorTo(xPos, yPos+10);
+  x = 32;
+  for (int i=x; i<x+16; i++) {
+    m.serialprint7(i);
+    m.serialprint7(9);
+  }
+
+  m.moveCursorTo(xPos, yPos+12);
+  for (int i=x+16; i<x+32; i++) {
+    m.serialprint7(i);
+    m.serialprint7(9);
+  }
+
+  m.moveCursorTo(xPos, yPos+14);
+  for (int i=x+32; i<x+48; i++) {
+    m.serialprint7(i);
+    m.serialprint7(9);
+  }
+
+  m.moveCursorTo(xPos, yPos+16);
+  for (int i=x+48; i<x+64; i++) {
+    m.serialprint7(i);
+    m.serialprint7(9);
+  }
+  m.useDefaultColors();
+  m.noPixelate();
+}
+
+
+void demoCursor() {
+  m.clearScreen();
+  m.mode(TEXT_MODE);
+  m.textColor(WHITE);
+  m.bgColor(RED);
+  m.text(" CURSOR DEMO ", 4, 1);
+  m.bgColor(BLACK);
+
+  m.cursor();
+
+  int pause = 1000;
+  m.moveCursorTo(TOP_LEFT);
+  delay(pause);
+  m.moveCursor(RIGHT, 39);
+  delay(pause);
+  m.moveCursor(DOWN, 23);
+  delay(pause);
+  m.moveCursor(LEFT, 39);
+  delay(pause);
+  m.moveCursor(UP, 23);
+  delay(pause);
+  m.moveCursor(RIGHT, 19);
+  delay(pause);
+  m.moveCursor(DOWN, 12);
+  delay(pause);
+  m.moveCursorTo(HOME);
+  delay(pause);
+  m.moveCursorTo(TOP_RIGHT);
+  delay(pause);
+  m.moveCursorTo(BOTTOM_LEFT);
+  delay(pause);
+  m.moveCursorTo(BOTTOM_RIGHT);
+  delay(pause);
+  m.moveCursorTo(TOP_LEFT);
+  delay(pause);
+  m.moveCursorTo(CENTER);
+  m.noCursor();
+}
+
+
+void demoCharacters() {
+  m.clearScreen();
+  m.mode(TEXT_MODE);
+  m.textColor(WHITE);
+  m.bgColor(RED);
+  m.text(" CHARACTERS DEMO ", 4, 1);
+  m.bgColor(BLACK);
+
+
+  int xPos = 3;
+  int yPos = 5;
+  m.cursor();
+
+  // a->z
+  m.moveCursorTo(xPos, yPos);
+  for (int i=97; i<97+26; i++) {
+    m.serialprint7(i);
+  }
+
+  // A->Z
+  m.moveCursorTo(xPos, yPos+1);
+  for (int i=65; i<65+26; i++) {
+    m.serialprint7(i);
+  }
+
+  // 0-9 + punctuation marks, ...
+  m.moveCursorTo(xPos, yPos+2);
+  for (int i=33; i<33+32; i++) {
+    m.serialprint7(i);
+  }
+  for (int i=91; i<97; i++) {
+    m.serialprint7(i);
+  }
+
+  // Colored characters
+  m.moveCursorTo(xPos, yPos+3);
+  m.textColor(RED);
+  for (int i=97; i<97+26; i++) {
+    m.serialprint7(i);
+  }
+  m.textColor(WHITE);
+
+  // Double width 1/2
+  m.moveCursorTo(xPos, yPos+4);
+  m.charSize(SIZE_DOUBLE_WIDTH);
+  for (int i=97; i<97+13; i++) {
+    m.serialprint7(i);
+  }  
+  m.moveCursorTo(xPos, yPos+5);
+  for (int i=97+13; i<97+26; i++) {
+    m.serialprint7(i);
+  }
+  m.charSize(SIZE_NORMAL);
+
+  // Special characters
+  m.moveCursorTo(xPos, yPos+6);
+  byte chars[] = {
+    SPE_CHAR_BOOK, SPE_CHAR_PARAGRAPH, SPE_CHAR_ARROW_LEFT, SPE_CHAR_ARROW_UP, SPE_CHAR_ARROW_RIGHT, SPE_CHAR_ARROW_DOWN, SPE_CHAR_CIRCLE, SPE_CHAR_MINUS_PLUS, SPE_CHAR_1_4, SPE_CHAR_1_2, SPE_CHAR_3_4, SPE_CHAR_UPPER_OE, SPE_CHAR_LOWER_OE, SPE_CHAR_BETA                  };
+  for (int i=0; i<sizeof(chars); i++) {
+    m.specialChar(chars[i]);
+  }
+
+  // Blink
+  m.moveCursorTo(xPos, yPos+7);
+  m.blink();
+  for (int i=97; i<97+26; i++) {
+    m.serialprint7(i);
+  }
+  m.noBlink();
+
+  // Invert video
+  m.moveCursorTo(xPos, yPos+8);
+  m.invertVideo();
+  for (int i=97; i<97+26; i++) {
+    m.serialprint7(i);
+  }
+  m.standardVideo();
+
+
+  // Transparent
+  // No effet on Minitel 1
+  m.moveCursorTo(xPos, yPos+9);
+  m.transparentVideo();
+  for (int i=97; i<97+26; i++) {
+    m.serialprint7(i);
+  }
+  m.standardVideo();
+}
+
+
+void demoBip() {
+  m.clearScreen();
+  m.mode(TEXT_MODE);
+  m.textColor(WHITE);
+  m.bgColor(RED);
+  m.text(" BIP DEMO ", 4, 1);
+  m.bgColor(BLACK);
+  
+  for (int i=0; i<2; i++) {
+    m.bip(50);
+    delay(700);
+    m.bip(5);
+    delay(500);
+    m.bip(10);
+    delay(2000);
+  }
+}
+
+void demoText() {
+  m.clearScreen();
+  m.mode(TEXT_MODE);
+  m.textColor(WHITE);
+  m.bgColor(RED);
+  m.text(" TEXT DEMO ", 4, 1);
+  m.bgColor(BLACK);
+
+  m.cursor();
+  m.text("****************************************", 1, 8);
+  m.blink();
+  m.text("CAUTION", 17, 13);
+  m.noBlink();
+  m.text("This is a test", 13, 15);
+  m.text("****************************************", 1, 20);
+  m.noCursor(); 
+}
+
+void demoColor() {
+
+  m.clearScreen();
+  m.mode(TEXT_MODE);
+  m.textColor(WHITE);
+  m.bgColor(RED);
+  m.text(" COLORS DEMO ", 4, 1);
+
+  m.mode(GRAPHIC_MODE);
+  m.bgColor(RED);
+  m.rect((byte) m.getGraphicChar("011001"), 4, 4, 33, 20);
+
+  for(int i=0; i<18; i++) {
+    m.moveCursorTo(5, 5+i);
+
+    m.textColor(WHITE);
+    m.textByte(m.getGraphicChar("111111"));
+    m.repeat(3);
+
+    m.textColor(YELLOW);
+    m.textByte(m.getGraphicChar("111111"));
+    m.repeat(3);
+
+    m.textColor(CYAN);
+    m.textByte(m.getGraphicChar("111111"));
+    m.repeat(3);
+
+    m.textColor(GREEN);
+    m.textByte(m.getGraphicChar("111111"));
+    m.repeat(3);
+
+    m.textColor(BLUE);
+    m.textByte(m.getGraphicChar("111111"));
+    m.repeat(3);
+
+    m.textColor(RED);
+    m.textByte(m.getGraphicChar("111111"));
+    m.repeat(3);
+
+    m.textColor(MAGENTA);
+    m.textByte(m.getGraphicChar("111111"));
+    m.repeat(3);
+
+    m.textColor(BLACK);
+    m.textByte(m.getGraphicChar("111111"));
+    m.repeat(3);
+  }
+}
+