Drake is the name of the computer I am developing. However, this blog covers all aspects of embedded hardware and software, and explains various projects in detail. Feedback is greatly appreciated.
donderdag 17 oktober 2013
Old FPGA project
At one point, quite some time ago, I played with my Spartan FPGA. I'm reminded of this because the font was similar to the font I'm using for my new phone. I only found this one screen shot (the blog at the time is gone). As you can see some parts came out pretty nicely, though.
woensdag 16 oktober 2013
Proportional fonts
In this post I added the code so far. It basically has the control for the LCD display (some of it came from the original sample code, although I changed quite a few pieces to be more readable/faster/more efficient) and connects the output of the SIM900 to the display (although everything is still copied to the PC using the hardware serial port as well). Once I have an input device on my phone this connection will be severed, which hopefully will return the 4k memory currently in use for the software serial connection (as I can switch the SIM900 to use the hardware UART). The part that changed compared to yesterday is highlighted in yellow. Basically, when the left side of a font is empty, I shift the character one to the left (which is fine, because there is always a single pixel between characters). If there are one, two or three columns to the right of the font empty, I will reduce the width of the character accordingly. If the bottom row is empty, and it is a character, I shift the character one down (which is fine, because there is always a single pixel below characters). This means a lot more characters might fit on a line, if they are of the narrow variety (e.g. 'i' and 'l').
// Maarten's phone.
// Copyright 2013, Maarten Hofman.
#include
byte Font[] = {
0x00, 0x00, //
0x09, 0x10, // !
0x05, 0x00, // "
0xC5, 0x86, // #
0xDA, 0xA8, // $
0x85, 0x52, // %
0xC3, 0x76, // &
0x04, 0x00, // '
0x04, 0xC4, // (
0x41, 0x12, // )
0xD5, 0xD6, // *
0xD0, 0x80, // +
0x00, 0x12, // ,
0xC0, 0x80, // -
0x00, 0x10, // .
0x84, 0x12, // /
0xAA, 0x29, // 0
0x24, 0x48, // 1
0xE2, 0xF1, // 2
0xA2, 0xE8, // 3
0xE8, 0xC8, // 4
0xCA, 0xB8, // 5
0xCA, 0xA9, // 6
0xA2, 0xC8, // 7
0xEA, 0xA9, // 8
0xEA, 0xC8, // 9
0x10, 0x00, // :
0x10, 0x12, // ;
0x84, 0x44, // <
0xC0, 0xA0, // =
0x81, 0x12, // >
0xE2, 0x90, // ?
0x2A, 0xE1, // @
0xEA, 0xD9, // A
0xEB, 0xB9, // B
0x0A, 0x21, // C
0x2B, 0x39, // D
0xCA, 0x31, // E
0xCA, 0x11, // F
0x0A, 0xA9, // G
0xE8, 0xD9, // H
0x92, 0x20, // I
0x20, 0x38, // J
0xCC, 0x55, // K
0x08, 0x71, // L
0xAD, 0x59, // M
0xA9, 0x5D, // N
0x2A, 0x29, // O
0xEA, 0x91, // P
0xAA, 0x6D, // Q
0xEA, 0xD5, // R
0xCA, 0xA8, // S
0x92, 0x00, // T
0x28, 0x29, // U
0x45, 0xA6, // V
0xB8, 0x79, // W
0x85, 0x56, // X
0x95, 0x00, // Y
0x86, 0x72, // Z
0x0B, 0x31, // [
0x81, 0x44, //
0x26, 0x68, // ]
0x2A, 0x00, // ^
0x00, 0x70, // _
0x01, 0x00, // `
0xE2, 0xE9, // a
0xC8, 0xB9, // b
0xC0, 0xA1, // c
0xE0, 0xE9, // d
0xEA, 0xA1, // e
0x4A, 0x11, // f
0xEA, 0xB8, // g
0xC8, 0xD9, // h
0x01, 0x11, // i
0x04, 0x28, // j
0xC8, 0xD5, // k
0x08, 0x11, // l
0xD0, 0xD9, // m
0xC0, 0xD9, // n
0xC0, 0xA9, // o
0xEA, 0x81, // p
0xEA, 0xC8, // q
0xC0, 0x91, // r
0x84, 0xA8, // s
0x48, 0x21, // t
0x00, 0x79, // u
0x00, 0x29, // v
0x90, 0x29, // w
0x85, 0x06, // x
0xE8, 0xA8, // y
0xC0, 0xE4, // z
0x4B, 0x21, // {
0x90, 0x00, // |
0x26, 0xA8, // }
0xAD, 0x00, // ~
0xFF, 0xFF, // DEL
};
/* 4-bit serial communication LDS183 LCD module */
const int SCOMMAND = 0;
const int SDATA = 1;
#define DC PIND4
#define CS PIND2
#define SDA PIND6
#define RESET PIND3
#define CLK PIND5
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
byte gr = 255;
byte gg = 255;
byte gb = 255;
SoftwareSerial GPRS(7, 8);
unsigned char buffer[64]; // buffer array for data receive over serial port
int count = 0; // counter for buffer array
byte cursor_x = 0;
byte cursor_y = 0;
void setup () {
DDRD = 0x7C;
lcdInit();
GPRS.begin(9600); // the GPRS baud rate
Serial.begin(9600); // the Serial port of Arduino baud rate.
}
void loop() {
int i, j, k, l;
setXY(0, 0, 128, 128); // Initial screen size
for (i = 0; i < 128 * 128; i++) { // black background
clearPixel();
}
setColor(255, 255, 255);
printString("Goliath online...\n");
//printString("!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~");
while (true) {
if (GPRS.available()) {
// if date is comming from softwareserial port ==> data is comming from gprs shield
while(GPRS.available()) {
// reading data into char array
byte in = GPRS.read();
buffer[count++] = in;
printChar(in);
// writing data into array
if(count == 64) break;
}
// if no data transmission ends, write buffer to hardware serial port
Serial.write(buffer, count);
// set counter of while loop to zero
count = 0;
}
if (Serial.available()) // if data is available on hardwareserial port ==> data is comming from PC or notebook
GPRS.write(Serial.read()); // write it to the GPRS shield
}
}
void lcdInit() {
cbi(PORTD, CS);
cbi(PORTD, SDA);
sbi(PORTD, CLK);
sbi(PORTD, RESET);
cbi(PORTD, RESET);
sbi(PORTD, RESET);
sbi(PORTD, CLK);
sbi(PORTD, SDA);
sbi(PORTD, CLK);
delay(10);
sendCMD(0x01); // Software Reset
// Write Contrast
sendCMD(0x25);
sendData(64);
//Sleep Out and booster on
sendCMD(0x11);
delay(10);
// Display Inversion off
sendCMD(0x20);
// Idle Mode off
sendCMD(0x38);
// Display on
sendCMD(0x29);
// Normal Mode on
sendCMD(0x13);
// Memory Data Access control
sendCMD(0x36);
sendData(0x60);
sendCMD(0x3A);
sendData(5); //16-Bit per Pixel
// Frame Frequency Select
sendCMD(0xB4);
sendData(0x03);
sendData(0x08);
sendData(0x0b);
sendData(0x0e);
// Display Control
sendCMD(0xBA);
sendData(0x07);
sendData(0x0D);
}
void shiftBits(byte b, int dc) {
cbi(PORTD, CLK);
if ((b&128)!=0) sbi(PORTD, SDA); else cbi(PORTD, SDA);
sbi(PORTD, CLK);
cbi(PORTD, CLK);
if ((b&64)!=0) sbi(PORTD, SDA); else cbi(PORTD, SDA);
sbi(PORTD, CLK);
cbi(PORTD, CLK);
if ((b&32)!=0) sbi(PORTD, SDA); else cbi(PORTD, SDA);
sbi(PORTD, CLK);
cbi(PORTD, CLK);
if ((b&16)!=0) sbi(PORTD, SDA); else cbi(PORTD, SDA);
sbi(PORTD, CLK);
cbi(PORTD, CLK);
if ((b&8)!=0) sbi(PORTD, SDA); else cbi(PORTD, SDA);
sbi(PORTD, CLK);
cbi(PORTD, CLK);
if ((b&4)!=0) sbi(PORTD, SDA); else cbi(PORTD, SDA);
sbi(PORTD, CLK);
cbi(PORTD, CLK);
if ((b&2)!=0) sbi(PORTD, SDA); else cbi(PORTD, SDA);
sbi(PORTD, CLK);
cbi(PORTD, CLK);
if ((b&1)!=0) sbi(PORTD, SDA); else cbi(PORTD, SDA);
if (dc == SDATA) sbi(PORTD, DC); else cbi(PORTD, DC);
sbi(PORTD, CLK);
}
//send data
inline void sendData(byte data) {
shiftBits(data, SDATA);
}
//send cmd
inline void sendCMD(byte data) {
shiftBits(data, SCOMMAND);
}
// Defines the area in which the pixels will be written, (x,y) is the top left, (dx,dy) is the size.
void setXY(byte x, byte y, byte dx, byte dy) {
sendCMD(0x2A);
sendData(x);
sendData(x+dx-1);
sendCMD(0x2B);
sendData(y);
sendData(y+dy-1);
sendCMD(0x2C);
}
//converts a 3*8Bit-RGB-Pixel to the 2-Byte-RGBRGB 565 Format of the Display
inline void setPixel(byte r, byte g, byte b) {
sendData((r & 248) | g >> 5);
sendData((g & 7) << 5 | b >> 3);
}
inline void setPixel() {
setPixel(gr, gg, gb);
}
inline void clearPixel() {
setPixel(0, 0, 0);
}
void printString(char *st) {
int stl, i;
stl = strlen(st);
for (i=0; i
printChar(*st++);
}
void newLine() {
cursor_x = 0;
cursor_y += 6;
if (cursor_y >= 122) {
cursor_y = 0;
}
setXY(0, cursor_y, 128, 6);
for (int i = 0; i < 128 * 6; i++) clearPixel();
}
void printChar(byte c) {
if (c < 32) {
if (c == 10) newLine();
} else {
cursor_x += printChar(c, cursor_x, cursor_y);
}
if (cursor_x > 122) newLine();
}
// Returns the width of the character.
byte printChar(byte c, byte x, byte y) {
byte p1, p2;
int iFont;
byte width = 6;
iFont = (c - ' ') * 2;
if ((iFont < 0) || (iFont > 254)) iFont = 254;
p1 = Font[iFont];
p2 = Font[iFont+1];
// Handle proportional fonts.
if ((p1 & 9) + (p2 & 17) == 0) {
width--;
x--;
}
if ((p1 & 36) + (p2 & 72) == 0) {
width--;
if ((p1 & 6) + (p2 & 164) == 0) {
width--;
if ((p1 & 146) + (p2 & 32) == 0) width--;
}
}
if ((c & 64) && ((p2 & 112) == 0)) y++;
setXY(x, y, 5, 5);
// Line 1
if (p1 & 1) setPixel(); else clearPixel();
if (p1 & 2) {
setPixel();
setPixel();
setPixel();
} else {
clearPixel();
clearPixel();
clearPixel();
}
if (p1 & 4) setPixel(); else clearPixel();
// Line 2
if (p1 & 8) setPixel(); else clearPixel();
if (p1 & 1) setPixel(); else clearPixel();
if (p1 & 16) setPixel(); else clearPixel();
if (p1 & 4) setPixel(); else clearPixel();
if (p1 & 32) setPixel(); else clearPixel();
// Line 3
if (p1 & 8) setPixel(); else clearPixel();
if (p1 & 64) setPixel(); else clearPixel();
if (p1 & 128) setPixel(); else clearPixel();
if (p2 & 128) setPixel(); else clearPixel();
if (p1 & 32) setPixel(); else clearPixel();
// Line 4
if (p2 & 1) setPixel(); else clearPixel();
if (p2 & 2) setPixel(); else clearPixel();
if (p1 & 16) setPixel(); else clearPixel();
if (p2 & 4) setPixel(); else clearPixel();
if (p2 & 8) setPixel(); else clearPixel();
// Line 5
if (p2 & 16) setPixel(); else clearPixel();
if (p2 & 32) {
setPixel();
setPixel();
setPixel();
} else {
clearPixel();
clearPixel();
clearPixel();
}
if (p2 & 64) setPixel(); else clearPixel();
return width;
}
void setColor(byte r, byte g, byte b) {
gr = r;
gg = g;
gb = b;
}
// Maarten's phone.
// Copyright 2013, Maarten Hofman.
#include
byte Font[] = {
0x00, 0x00, //
0x09, 0x10, // !
0x05, 0x00, // "
0xC5, 0x86, // #
0xDA, 0xA8, // $
0x85, 0x52, // %
0xC3, 0x76, // &
0x04, 0x00, // '
0x04, 0xC4, // (
0x41, 0x12, // )
0xD5, 0xD6, // *
0xD0, 0x80, // +
0x00, 0x12, // ,
0xC0, 0x80, // -
0x00, 0x10, // .
0x84, 0x12, // /
0xAA, 0x29, // 0
0x24, 0x48, // 1
0xE2, 0xF1, // 2
0xA2, 0xE8, // 3
0xE8, 0xC8, // 4
0xCA, 0xB8, // 5
0xCA, 0xA9, // 6
0xA2, 0xC8, // 7
0xEA, 0xA9, // 8
0xEA, 0xC8, // 9
0x10, 0x00, // :
0x10, 0x12, // ;
0x84, 0x44, // <
0xC0, 0xA0, // =
0x81, 0x12, // >
0xE2, 0x90, // ?
0x2A, 0xE1, // @
0xEA, 0xD9, // A
0xEB, 0xB9, // B
0x0A, 0x21, // C
0x2B, 0x39, // D
0xCA, 0x31, // E
0xCA, 0x11, // F
0x0A, 0xA9, // G
0xE8, 0xD9, // H
0x92, 0x20, // I
0x20, 0x38, // J
0xCC, 0x55, // K
0x08, 0x71, // L
0xAD, 0x59, // M
0xA9, 0x5D, // N
0x2A, 0x29, // O
0xEA, 0x91, // P
0xAA, 0x6D, // Q
0xEA, 0xD5, // R
0xCA, 0xA8, // S
0x92, 0x00, // T
0x28, 0x29, // U
0x45, 0xA6, // V
0xB8, 0x79, // W
0x85, 0x56, // X
0x95, 0x00, // Y
0x86, 0x72, // Z
0x0B, 0x31, // [
0x81, 0x44, //
0x26, 0x68, // ]
0x2A, 0x00, // ^
0x00, 0x70, // _
0x01, 0x00, // `
0xE2, 0xE9, // a
0xC8, 0xB9, // b
0xC0, 0xA1, // c
0xE0, 0xE9, // d
0xEA, 0xA1, // e
0x4A, 0x11, // f
0xEA, 0xB8, // g
0xC8, 0xD9, // h
0x01, 0x11, // i
0x04, 0x28, // j
0xC8, 0xD5, // k
0x08, 0x11, // l
0xD0, 0xD9, // m
0xC0, 0xD9, // n
0xC0, 0xA9, // o
0xEA, 0x81, // p
0xEA, 0xC8, // q
0xC0, 0x91, // r
0x84, 0xA8, // s
0x48, 0x21, // t
0x00, 0x79, // u
0x00, 0x29, // v
0x90, 0x29, // w
0x85, 0x06, // x
0xE8, 0xA8, // y
0xC0, 0xE4, // z
0x4B, 0x21, // {
0x90, 0x00, // |
0x26, 0xA8, // }
0xAD, 0x00, // ~
0xFF, 0xFF, // DEL
};
/* 4-bit serial communication LDS183 LCD module */
const int SCOMMAND = 0;
const int SDATA = 1;
#define DC PIND4
#define CS PIND2
#define SDA PIND6
#define RESET PIND3
#define CLK PIND5
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
byte gr = 255;
byte gg = 255;
byte gb = 255;
SoftwareSerial GPRS(7, 8);
unsigned char buffer[64]; // buffer array for data receive over serial port
int count = 0; // counter for buffer array
byte cursor_x = 0;
byte cursor_y = 0;
void setup () {
DDRD = 0x7C;
lcdInit();
GPRS.begin(9600); // the GPRS baud rate
Serial.begin(9600); // the Serial port of Arduino baud rate.
}
void loop() {
int i, j, k, l;
setXY(0, 0, 128, 128); // Initial screen size
for (i = 0; i < 128 * 128; i++) { // black background
clearPixel();
}
setColor(255, 255, 255);
printString("Goliath online...\n");
//printString("!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~");
while (true) {
if (GPRS.available()) {
// if date is comming from softwareserial port ==> data is comming from gprs shield
while(GPRS.available()) {
// reading data into char array
byte in = GPRS.read();
buffer[count++] = in;
printChar(in);
// writing data into array
if(count == 64) break;
}
// if no data transmission ends, write buffer to hardware serial port
Serial.write(buffer, count);
// set counter of while loop to zero
count = 0;
}
if (Serial.available()) // if data is available on hardwareserial port ==> data is comming from PC or notebook
GPRS.write(Serial.read()); // write it to the GPRS shield
}
}
void lcdInit() {
cbi(PORTD, CS);
cbi(PORTD, SDA);
sbi(PORTD, CLK);
sbi(PORTD, RESET);
cbi(PORTD, RESET);
sbi(PORTD, RESET);
sbi(PORTD, CLK);
sbi(PORTD, SDA);
sbi(PORTD, CLK);
delay(10);
sendCMD(0x01); // Software Reset
// Write Contrast
sendCMD(0x25);
sendData(64);
//Sleep Out and booster on
sendCMD(0x11);
delay(10);
// Display Inversion off
sendCMD(0x20);
// Idle Mode off
sendCMD(0x38);
// Display on
sendCMD(0x29);
// Normal Mode on
sendCMD(0x13);
// Memory Data Access control
sendCMD(0x36);
sendData(0x60);
sendCMD(0x3A);
sendData(5); //16-Bit per Pixel
// Frame Frequency Select
sendCMD(0xB4);
sendData(0x03);
sendData(0x08);
sendData(0x0b);
sendData(0x0e);
// Display Control
sendCMD(0xBA);
sendData(0x07);
sendData(0x0D);
}
void shiftBits(byte b, int dc) {
cbi(PORTD, CLK);
if ((b&128)!=0) sbi(PORTD, SDA); else cbi(PORTD, SDA);
sbi(PORTD, CLK);
cbi(PORTD, CLK);
if ((b&64)!=0) sbi(PORTD, SDA); else cbi(PORTD, SDA);
sbi(PORTD, CLK);
cbi(PORTD, CLK);
if ((b&32)!=0) sbi(PORTD, SDA); else cbi(PORTD, SDA);
sbi(PORTD, CLK);
cbi(PORTD, CLK);
if ((b&16)!=0) sbi(PORTD, SDA); else cbi(PORTD, SDA);
sbi(PORTD, CLK);
cbi(PORTD, CLK);
if ((b&8)!=0) sbi(PORTD, SDA); else cbi(PORTD, SDA);
sbi(PORTD, CLK);
cbi(PORTD, CLK);
if ((b&4)!=0) sbi(PORTD, SDA); else cbi(PORTD, SDA);
sbi(PORTD, CLK);
cbi(PORTD, CLK);
if ((b&2)!=0) sbi(PORTD, SDA); else cbi(PORTD, SDA);
sbi(PORTD, CLK);
cbi(PORTD, CLK);
if ((b&1)!=0) sbi(PORTD, SDA); else cbi(PORTD, SDA);
if (dc == SDATA) sbi(PORTD, DC); else cbi(PORTD, DC);
sbi(PORTD, CLK);
}
//send data
inline void sendData(byte data) {
shiftBits(data, SDATA);
}
//send cmd
inline void sendCMD(byte data) {
shiftBits(data, SCOMMAND);
}
// Defines the area in which the pixels will be written, (x,y) is the top left, (dx,dy) is the size.
void setXY(byte x, byte y, byte dx, byte dy) {
sendCMD(0x2A);
sendData(x);
sendData(x+dx-1);
sendCMD(0x2B);
sendData(y);
sendData(y+dy-1);
sendCMD(0x2C);
}
//converts a 3*8Bit-RGB-Pixel to the 2-Byte-RGBRGB 565 Format of the Display
inline void setPixel(byte r, byte g, byte b) {
sendData((r & 248) | g >> 5);
sendData((g & 7) << 5 | b >> 3);
}
inline void setPixel() {
setPixel(gr, gg, gb);
}
inline void clearPixel() {
setPixel(0, 0, 0);
}
void printString(char *st) {
int stl, i;
stl = strlen(st);
for (i=0; i
printChar(*st++);
}
void newLine() {
cursor_x = 0;
cursor_y += 6;
if (cursor_y >= 122) {
cursor_y = 0;
}
setXY(0, cursor_y, 128, 6);
for (int i = 0; i < 128 * 6; i++) clearPixel();
}
void printChar(byte c) {
if (c < 32) {
if (c == 10) newLine();
} else {
cursor_x += printChar(c, cursor_x, cursor_y);
}
if (cursor_x > 122) newLine();
}
// Returns the width of the character.
byte printChar(byte c, byte x, byte y) {
byte p1, p2;
int iFont;
byte width = 6;
iFont = (c - ' ') * 2;
if ((iFont < 0) || (iFont > 254)) iFont = 254;
p1 = Font[iFont];
p2 = Font[iFont+1];
// Handle proportional fonts.
if ((p1 & 9) + (p2 & 17) == 0) {
width--;
x--;
}
if ((p1 & 36) + (p2 & 72) == 0) {
width--;
if ((p1 & 6) + (p2 & 164) == 0) {
width--;
if ((p1 & 146) + (p2 & 32) == 0) width--;
}
}
if ((c & 64) && ((p2 & 112) == 0)) y++;
setXY(x, y, 5, 5);
// Line 1
if (p1 & 1) setPixel(); else clearPixel();
if (p1 & 2) {
setPixel();
setPixel();
setPixel();
} else {
clearPixel();
clearPixel();
clearPixel();
}
if (p1 & 4) setPixel(); else clearPixel();
// Line 2
if (p1 & 8) setPixel(); else clearPixel();
if (p1 & 1) setPixel(); else clearPixel();
if (p1 & 16) setPixel(); else clearPixel();
if (p1 & 4) setPixel(); else clearPixel();
if (p1 & 32) setPixel(); else clearPixel();
// Line 3
if (p1 & 8) setPixel(); else clearPixel();
if (p1 & 64) setPixel(); else clearPixel();
if (p1 & 128) setPixel(); else clearPixel();
if (p2 & 128) setPixel(); else clearPixel();
if (p1 & 32) setPixel(); else clearPixel();
// Line 4
if (p2 & 1) setPixel(); else clearPixel();
if (p2 & 2) setPixel(); else clearPixel();
if (p1 & 16) setPixel(); else clearPixel();
if (p2 & 4) setPixel(); else clearPixel();
if (p2 & 8) setPixel(); else clearPixel();
// Line 5
if (p2 & 16) setPixel(); else clearPixel();
if (p2 & 32) {
setPixel();
setPixel();
setPixel();
} else {
clearPixel();
clearPixel();
clearPixel();
}
if (p2 & 64) setPixel(); else clearPixel();
return width;
}
void setColor(byte r, byte g, byte b) {
gr = r;
gg = g;
gb = b;
}
dinsdag 15 oktober 2013
Cell Phone
It has been over a year since my last post, and you possibly think that I am idle. However, this isn't exactly true. After I got a 128x128 pixel 64k color display for Arduino, which I soldered together, I bought the Arduino as well and then wondered what my next project would be. Meandering through the mall I found a very inexpensive SIM900 GRPS chip, which worked well together with the other components I had. So I started building a cell phone, which currently is still in a preliminary stage, of which there are a few pictures here.
As you can see, the cell phone isn't exactly small (and this is without the microphone, speaker and input device) but it works a little bit (if you read the display correctly it says "Call ready" at the end). It's currently using 8 KB out of 32 KB, so I think I should be able to write at least a few services for it. It can do SMS, calls and even internet with a speed up to 86 kb/s (more than enough to download pictures to fill the display). I'm using an H2O subscription, which is very cheap ($10 for the SIM, and $10/90 days, unless I use a lot of money on calls ($0.05/minute), SMS ($0.10/message) or Internet ($0.10/MB). I'm still not entirely sure about the input mechanism, I'm considering a PS/2 keyboard, but will probably end up with up, down, left, right and submit as an interface.
As you can see, the cell phone isn't exactly small (and this is without the microphone, speaker and input device) but it works a little bit (if you read the display correctly it says "Call ready" at the end). It's currently using 8 KB out of 32 KB, so I think I should be able to write at least a few services for it. It can do SMS, calls and even internet with a speed up to 86 kb/s (more than enough to download pictures to fill the display). I'm using an H2O subscription, which is very cheap ($10 for the SIM, and $10/90 days, unless I use a lot of money on calls ($0.05/minute), SMS ($0.10/message) or Internet ($0.10/MB). I'm still not entirely sure about the input mechanism, I'm considering a PS/2 keyboard, but will probably end up with up, down, left, right and submit as an interface.
Abonneren op:
Posts (Atom)