/*

$13 LED Bitcoin ticker

For use with Arduino 16M,5V + TM1638 display module + enc28j60 type ethernet interface

Uses Bitstamp API (2014)

Hardware Required:

Arduino 16M, 5V ebay search: "arduino pro mini"

Display module ebay search: "TM1638 Key Display Module"

Ethernet module ebay search: "5V ENC28J60" (5V is IMPORTANT!)

Power supply ebay search: "usb wall charger"

enc28j60 module connections (5V module required):

Arduino pin 8 - enc28j60 CS

Arduino pin 11 - enc28j60 SDI

Arduino pin 12 - enc28j60 SDO

Arduino pin 13 - enc28j60 SCK

TM1638 "LED&KEY" module connections:

Arduino pin 2 - TM1638 CLK

Arduino pin 3 - TM1638 DIO

Arduino pin 4 - TM1638 STB

Requires TM1638 library, available at http://code.google.com/p/tm1638-library/

Requires EtherCard library, available at https://github.com/jcw/ethercard

*/

#include <EtherCard.h>

// ethernet interface mac address, must be unique on the LAN

static byte mymac [ ] = { 0x74 , 0x69 , 0x69 , 0x2D , 0x30 , 0x31 } ;

byte Ethernet :: buffer [ 700 ] ;

const char website [ ] PROGMEM = "www.bitstamp.net" ;

const char webfolder [ ] PROGMEM = "/api/ticker/" ;

const char price_tag [ ] = " \" last \" :" ;

#include <TM1638.h>

// define a TM1638 type display module on data pin 3, clock pin 2 and strobe pin 4

#define LED_INTENSITY 1 // 0 to 7

TM1638 module ( 3 , 2 , 4 , true , LED_INTENSITY ) ;

static char tick [ 8 ] ; // price display buffer

#define REFRESH_MSEC 60000 // refresh rate, msecs

static uint32_t timer ; // refresh timer, msecs

// called when web page data is ready

static void my_callback ( byte status , word off , word len )

{

Serial. println ( ">>>" ) ;

Ethernet :: buffer [ 699 ] = 0 ;

Serial. print ( ( const char * ) Ethernet :: buffer + off ) ;

Serial. println ( "..." ) ;

// scrape last price from web page

// yeah, this won't work if it happens to cross a block boundary

const char * p ;

p = strstr ( ( const char * ) Ethernet :: buffer + off , price_tag ) ;

if ( p ) // found the tag, a quoted decimal number should follow

{

p = strstr ( p , "." ) ; // key off of decimal point

if ( p )

{ const char * q ;

int i ;

for ( i = 0 ; i < 8 ; i ++ ) tick [ i ] = ' ' ; // space fill result buffer

// collect digits to the right of the decimal

for ( i = 0 , q = p + 1 ; i < 4 ; i ++, q ++ ) if ( * q == ' \" ' ) break ; else tick [ i + 4 ] = * q ;

// collect digits to the left of the decimal

for ( i = 0 , q = p - 1 ; i < 4 ; i ++, q -- ) if ( * q == ' \" ' ) break ; else tick [ 3 - i ] = * q ;

}

// refresh the LED display

module. setDisplayToString ( tick , 0x10 , 0 ) ; // decimal point at position 4

}

}

void setup ( ) // arduino standard startup

{

module. clearDisplay ( ) ;

module. setDisplayToString ( "bitcoin" ) ;

Serial. begin ( 57600 ) ;

Serial. println ( F ( "

[bitcoin ticker]" ) ) ;

if ( ether. begin ( sizeof Ethernet :: buffer , mymac ) == 0 )

{ Serial. println ( F ( "Failed to access Ethernet controller" ) ) ;

module. setDisplayToString ( " eth Err" ) ;

}

if ( ! ether. dhcpSetup ( ) )

{ Serial. println ( F ( "DHCP failed" ) ) ;

module. setDisplayToString ( "dhcp Err" ) ;

}

ether. printIp ( "IP: " , ether. myip ) ;

ether. printIp ( "GW: " , ether. gwip ) ;

ether. printIp ( "DNS: " , ether. dnsip ) ;

if ( ! ether. dnsLookup ( website ) )

{ Serial. println ( "DNS failed" ) ;

module. setDisplayToString ( " dns Err" ) ;

}

ether. printIp ( "SRV: " , ether. hisip ) ;

}

void loop ( ) // arduino standard bigloop

{

// this particular "LED&KEY" board has 8 red leds & 8 buttons

byte keys = module. getButtons ( ) ;

module. setLEDs ( keys ) ; // show button pressed on leds

// the buttons set the [7 segment] display intensity

if ( keys != 0 )

{ // figure out which key is pressed

int k ; for ( k = 0 ; k < 8 ; k ++ ) if ( ( keys & ( 1 << k ) ) != 0 ) break ;

// set display brightness

module. setupDisplay ( true , k ) ;

}

// ethernet stack driver

ether. packetLoop ( ether. packetReceive ( ) ) ;

// price refresh

if ( millis ( ) > timer )

{

timer = millis ( ) + REFRESH_MSEC ;

Serial. println ( ) ;

Serial. print ( "<<< REQ " ) ;

// request price from web api; it'll display when callback executes

ether. persistTcpConnection ( true ) ; // repetitively callback for large web page

ether. browseUrl ( webfolder , "" , website , my_callback ) ;

}