Skip to content

Instantly share code, notes, and snippets.

@trunner10
Created August 27, 2015 02:29
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save trunner10/fd5516aa7533a7168aee to your computer and use it in GitHub Desktop.
Save trunner10/fd5516aa7533a7168aee to your computer and use it in GitHub Desktop.
Use web to change Tivo channel
#ifndef ethernet_h
#define ethernet_h
#include <inttypes.h>
//#include "w5100.h"
#include "IPAddress.h"
#include "EthernetClient.h"
#include "EthernetServer.h"
#include "Dhcp.h"
#define MAX_SOCK_NUM 4
class EthernetClass {
private:
IPAddress _dnsServerAddress;
DhcpClass* _dhcp;
public:
static uint8_t _state[MAX_SOCK_NUM];
static uint16_t _server_port[MAX_SOCK_NUM];
// Initialise the Ethernet shield to use the provided MAC address and gain the rest of the
// configuration through DHCP.
// Returns 0 if the DHCP configuration failed, and 1 if it succeeded
int begin(uint8_t *mac_address);
void begin(uint8_t *mac_address, IPAddress local_ip);
void begin(uint8_t *mac_address, IPAddress local_ip, IPAddress dns_server);
void begin(uint8_t *mac_address, IPAddress local_ip, IPAddress dns_server, IPAddress gateway);
void begin(uint8_t *mac_address, IPAddress local_ip, IPAddress dns_server, IPAddress gateway, IPAddress subnet);
int maintain();
IPAddress localIP();
IPAddress subnetMask();
IPAddress gatewayIP();
IPAddress dnsServerIP();
friend class EthernetClient;
friend class EthernetServer;
};
extern EthernetClass Ethernet;
#endif
#include <Ethernet.h>
#include <SPI.h>
#include <IRremote.h>
#include <IRCodes.h>
IRsend irsend;
boolean reading = false;
String temp;
#define test 4294967295
char type;
int toggle = 0;
////////////////////////////////////////////////////////////////////////
//Usage
////////////////////////////////////////////////////////////////////////
//Go to webpage and enter 192.168.1.137?T820 for ch 820
////////////////////////////////////////////////////////////////////////
//CONFIGURE
////////////////////////////////////////////////////////////////////////
byte ip[] = { 192,168,1, 137 }; //Manual setup only
byte gateway[] = { 192,168,1,1 }; //Manual setup only
byte subnet[] = { 255, 255, 255, 0 }; //Manual setup only
// if need to change the MAC address (Very Rare)
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
EthernetServer server = EthernetServer(80); //port 80
////////////////////////////////////////////////////////////////////////
void setup(){
Serial.begin(9600);
//Pins 10,11,12 & 13 are used by the ethernet shield
//pinMode(2, OUTPUT);
//pinMode(3, OUTPUT);
//pinMode(4, OUTPUT);
//pinMode(5, OUTPUT);
//pinMode(6, OUTPUT);
//pinMode(7, OUTPUT);
//pinMode(8, OUTPUT);
//pinMode(9, OUTPUT);
Ethernet.begin(mac);
Ethernet.begin(mac, ip, gateway, subnet); //for manual setup
server.begin();
Serial.println(Ethernet.localIP());
}
void loop(){
// listen for incoming clients, and process qequest.
checkForClient();
}
void checkForClient(){
EthernetClient client = server.available();
if (client) {
// an http request ends with a blank line
boolean currentLineIsBlank = true;
boolean sentHeader = false;
while (client.connected()) {
if (client.available()) {
if(!sentHeader){
// send a standard http response header
client.println("HTTP/1.1 200 OK");
client.println("Content-Type: text/html");
client.println();
sentHeader = true;
}
//char type = SAMSUNG_TV;
char c = client.read();
if(reading && c == ' ') reading = false;
if(c == '?'){
type = client.read(); //first letter is the type, Ignore for now
reading = true; //found the ?, begin reading the info
}
if(reading){
//Serial.println(c);
sendIRChannel(c,type,client);
//temp = temp + c;
}
//sendIRChannel(c,type,client);
if (c == '\n' && currentLineIsBlank) break;
if (c == '\n') {
currentLineIsBlank = true;
}else if (c != '\r') {
currentLineIsBlank = false;
}
}
}
//Serial.println(temp);
delay(1); // give the web browser time to receive the data
client.stop(); // close the connection:
}
}
void sendIRChannel(char channel, char type, EthernetClient client)
{
switch (channel) {
case '0':
tivoSendIR(tivoCh0, "Tivo : Ch 0", client);
break;
case '1':
tivoSendIR(tivoCh1, "Tivo : Ch 1", client);
break;
case '2':
tivoSendIR(tivoCh2, "Tivo : Ch 2", client);
break;
case '3':
tivoSendIR(tivoCh3, "Tivo : Ch 3", client);
break;
case '4':
tivoSendIR(tivoCh4, "Tivo : Ch 4", client);
break;
case '5':
tivoSendIR(tivoCh5, "Tivo : Ch 5", client);
break;
case '6':
tivoSendIR(tivoCh6, "Tivo : Ch 6", client);
break;
case '7':
tivoSendIR(tivoCh7, "Tivo : Ch 7", client);
break;
case '8':
tivoSendIR(tivoCh8, "Tivo : Ch 8", client);
break;
case '9':
tivoSendIR(tivoCh9, "Tivo : Ch 9", client);
break;
case 'G':
tivoSendIR(tivoGuide, "Tivo : Guide", client);
break;
}
}
void tivoSendIR(long unsigned int command, const char* text, EthernetClient client){
client.print(text);
client.print("<br>");
Serial.println(text);
irsend.sendNEC(command, 32);
delay(500);
}
//Use IRrecvRead for these codes
#define SONY_TV 's'
#define sonyTVPower 0xA90
#define sonyTVCh1 0x10
#define sonyTVCh2 0x810
#define sonyTVCh3 0x410
#define sonyTVCh4 0xC10
#define sonyTVCh5 0x210
#define sonyTVCh6 0xA10
#define sonyTVCh7 0x610
#define sonyTVCh8 0xE10
#define sonyTVCh9 0x110
#define sonyTVCh0 0x910
#define sonyTVChUp 0x90
#define sonyTVChDown 0x890
#define sonyTVPrevCh 0xDD0
#define sonyTVVolUp 0x490
#define sonyTVVolDown 0xC90
#define sonyTVMute 0x290
#define sonyTVEnter 0xD10
#define SAMSUNG_TV 'S'
#define samsungTVPower 0xE0E040BF
#define samsungTVCh1 0xE0E020DF
#define samsungTVCh2 0xE0E0A05F
#define samsungTVCh3 0xE0E0609F
#define samsungTVCh4 0xE0E010EF
#define samsungTVCh5 0xE0E0906F
#define samsungTVCh6 0xE0E050AF
#define samsungTVCh7 0xE0E030CF
#define samsungTVCh8 0xE0E0B04F
#define samsungTVCh9 0xE0E0708F
#define samsungTVCh0 0xE0E08877
#define samsungTVDash 0xE0E0C43B
#define samsungTVVolUp 0xE0E0E01F
#define samsungTVVolDown 0xE0E0D02F
#define samsungTVChUp 0xE0E048B7
#define samsungTVChDown 0xE0E008F7
#define samsungTVMute 0xE0E0F00F
#define samsungTVPrevCh 0xE0E0C837
#define samsungTVSource 0xE0E0807F
#define samsungTVEnter 0xE0E016E9
#define samsungTVMenu 0xE0E058A7
#define samsungTVTools 0xE0E0D22D
#define samsungTVUpArrow 0xE0E006F9
#define samsungTVDownArrow 0xE0E08679
#define samsungTVRightArrow 0xE0E046B9
#define samsungTVLeftArrow 0xE0E0A659
#define samsungTVExit 0xE0E0B44B
#define samsungTVReturn 0xE0E01AE5
// NEC 32 bit
#define TIVO 'T'
#define tivoCh1 0xA10C140B
#define tivoCh2 0xA10C940B
#define tivoCh3 0xA10C540B
#define tivoCh4 0xA10CD40B
#define tivoCh5 0xA10C340B
#define tivoCh6 0xA10CB40B
#define tivoCh7 0xA10C740B
#define tivoCh8 0xA10CF40B
#define tivoCh9 0xA10C0C03
#define tivoCh0 0xA10C8C03
#define tivoClear 0xA10C4C03
#define tivoEnter 0xA10CCC03
#define tivoGuide 0xA10C6C03
#define tivoYellow 0xA10C0609
#define tivoBlue 0xA10C8609
#define tivoRed 0xA10C4609
#define tivoGreen 0xA10CC609
//A10C6C03
//Decoded NEC: A10C6C03 (32 bits)
//Raw (68): 26420 8850 -4550 550 -1650 550 -550 550 -1650 550 -550 550 -550 550 -550 550 -550 550 -1650 550 -550 550 -550 550 -550 550 -550 550 -1650 550 -1650 550 -550 550 -550 550 -550 550 -1650 550 -1650 550 -550 500 -1700 500 -1700 500 -600 500 -550 550 -550 550 -550 550 -550 550 -550 550 -550 550 -550 550 -1650 550 -1650 550
// NEC 32 bit
#define HARMAN 'H'
#define harmanPowerOn 0x10E03FC
#define harmanPowerOff 0x10EF906
#define harmanVolUp 0x10EE31C
#define harmanVolDown 0x10E13EC
#define harmanMute 0x10E837C
#define harmanVid1 0x10E53AC
#define harmanVid2 0x10ED32C
#define harmanVid3 0x10E738C
#define harmanVid4 0x10E8B74
#define harmanDim 0x10E3BC4
#define harmanSurr 0x414E1AE5
#define harmanDolby 0xC8A229F9
#define harmanDTS 0x414E05FA
#define harmanLog7 0x483637C2
#define harmanStereo 0x414ED926
#define harmanNEO 0x5C43515A
// NEC 32 bit
#define TUNERONE '1'
#define tuneronePower 0xFFD02F
#define tuneroneCh1 0xFF10EF
#define tuneroneCh2 0xFF906F
#define tuneroneCh3 0xFF50AF
#define tuneroneCh4 0xFF30CF
#define tuneroneCh5 0xFFB04F
#define tuneroneCh6 0xFF708F
#define tuneroneCh7 0xFF08F7
#define tuneroneCh8 0xFF8877
#define tuneroneCh9 0xFF48B7
#define tuneroneCh0 0xFFA857
#define tuneroneChP 0xFF6897
#define tuneroneEnter 0xFF7887
// RC6 36 bit
#define XBOX 'X'
unsigned long long xboxPower = 0xc800F040CLL;
#define xboxCh1 0x800F8401
#define xboxCh2 0x800F0402
#define xboxCh3 0x800F8403
#define xboxCh4 0x800F0404
#define xboxCh5 0x800F8405
#define xboxCh6 0x800F0406
#define xboxCh7 0x800F8407
#define xboxCh8 0x800F0408
#define xboxCh9 0x800F8409
#define xboxCh0 0x800F0400
#define xboxChUp 0x800F8412
#define xboxChDown 0x800F0413
#define xboxEnter 0x800F840B
#define xboxClear 0x800F040A
#define xboxRecTV 0x800F8448
#define xboxGuide 0x800F0426
#define xboxLiveTv 0x800F8425
#define xboxUpArrow 0x800F041E
#define xboxDownArrow 0x800F841F
unsigned long long xboxRightArrow = 0xc800F0421LL;
#define xboxLeftArrow 0x800F8420
#define xboxOk 0x800F0422
#define xboxBack 0x800F8423
#define xboxInfo 0x800F040F
#define xboxWindows 0x800F840D
#define xboxSkipForward 0x800F041A
#define xboxSkipBackward 0x800F841B
#define xboxRW 0x800F0415
#define xboxFF 0x800F8414
#define xboxRec 0x800F0417
#define xboxPause 0x800F8418
#define xboxStop 0x800F0419
#define xboxPlay 0x800F8416
#define cableCh1 0x92DF9279
unsigned int dvrGuide[34] = {-9450,600,-2150,550,-2150,600,-2150,550,-2150,600,-4450,600,-4450,600,-2100,600,-2150,550,-2150,600,-2150,600,-2150,550,-2150,600,-4450,600,-2100,600,-4450,600,-4450,600};
//unsigned int samsungTVPower[68] = {4550,4400,650,1600,650,1550,650,1600,650,450,650,500,650,450,650,450,650,450,650,1600,650,1550,650,1600,650,450,650,500,650,450,650,450,650,450,700,450,650,1550,650,500,650,450,650,450,650,450,650,500,650,450,650,1600,650,450,650,1550,650,1600,650,1550,650,1600,650,1550,650,1600,650};
//unsigned int samsungTVCh1[68] = {4500,4450,600,1650,600,1600,650,1600,600,500,650,500,600,500,600,500,600,500,650,1600,600,1600,650,1600,600,500,650,500,600,500,600,500,650,500,600,500,600,500,600,1650,600,500,600,500,600,500,650,500,600,500,600,1650,600,1600,600,500,650,1600,600,1600,650,1600,600,1600,650,1600,600};
//unsigned int samsungTVCh2[68] = {4500,4450,600,1600,650,1600,600,1650,600,500,600,500,600,500,650,500,600,500,600,1650,600,1600,600,1650,600,500,600,500,600,500,650,500,600,500,600,1650,600,500,600,1600,650,500,600,500,600,500,600,550,600,500,600,500,600,1650,600,500,600,1600,600,1650,600,1600,650,1600,600,1600,650};
//unsigned int samsungTVCh3[68] = {4500,4450,600,1600,650,1600,650,1600,600,500,600,500,650,450,650,500,600,500,650,1550,650,1600,650,1600,600,500,600,500,650,450,650,500,600,500,650,450,650,1600,600,1600,650,500,600,500,650,450,650,450,650,500,600,1600,650,450,650,500,650,1550,650,1600,650,1550,650,1600,650,1550,650};
//unsigned int samsungTVCh4[68] = {4500,4450,600,1650,600,1600,600,1650,600,500,600,550,600,500,600,500,600,500,600,1650,600,1600,600,1650,600,500,600,550,600,500,600,500,600,500,650,500,600,500,600,500,600,1650,600,500,600,500,650,500,600,500,600,1600,650,1600,600,1650,600,500,600,1600,600,1650,600,1600,650,1600,600};
//unsigned int samsungTVCh5[68] = {4500,4450,600,1650,600,1600,650,1600,600,500,650,500,600,500,600,500,600,500,600,1650,600,1600,600,1650,600,500,650,500,600,500,600,500,650,450,600,1650,600,500,650,450,600,1650,600,500,650,450,650,500,600,500,600,500,650,1600,600,1650,600,500,600,1600,600,1650,600,1600,650,1600,600};
//unsigned int samsungTVCh6[68] = {4500,4450,600,1650,600,1600,600,1650,600,500,600,500,650,500,600,500,600,500,600,1650,600,1600,600,1650,600,500,600,500,650,500,600,500,600,500,650,450,650,1600,600,500,600,1650,600,500,600,500,650,500,600,500,600,1650,600,500,600,1600,650,450,650,1600,600,1650,600,1600,600,1650,600};
//unsigned int samsungTVCh7[68] = {4500,4450,600,1650,600,1600,600,1650,600,500,600,550,600,500,600,500,600,500,600,1650,600,1600,650,1600,600,500,600,550,600,500,600,500,600,500,650,500,600,500,600,1600,650,1600,600,500,650,500,600,500,600,500,600,1650,600,1600,650,500,600,500,600,1600,650,1600,600,1600,650,1600,600};
//unsigned int samsungTVCh8[68] = {4550,4400,650,1550,650,1600,650,1550,700,450,650,450,650,450,650,500,650,450,650,1550,650,1600,650,1550,700,450,650,450,650,450,650,500,650,450,650,1550,700,400,650,1600,650,1600,650,450,650,450,650,500,650,450,650,450,650,1600,650,450,650,450,650,1600,650,1550,650,1600,650,1550,650};
//unsigned int samsungTVCh9[68] = {4550,4400,650,1600,650,1550,650,1600,650,450,700,450,650,450,650,450,650,450,700,1550,650,1550,700,1550,650,450,700,450,650,450,650,450,700,400,700,450,650,1550,650,1600,650,1550,700,450,650,450,650,450,700,400,650,1600,650,450,650,500,650,450,650,1550,700,1550,650,1550,650,1600,650};
//unsigned int samsungTVCh0[68] = {4500,4450,600,1600,650,1600,600,1600,650,500,600,500,650,450,650,500,600,500,600,1600,650,1600,650,1550,650,500,650,450,650,450,650,450,650,500,650,1550,650,500,600,500,650,450,650,1600,650,450,650,450,650,450,700,450,650,1550,650,1600,650,1550,650,500,650,1550,650,1600,650,1550,650};
//unsigned int samsungTVVolUp[68] = {4500,4450,650,1550,650,1600,650,1600,650,450,650,450,650,450,700,450,650,450,650,1550,650,1600,650,1600,650,450,650,450,650,450,700,450,650,450,650,1600,650,1550,650,1600,650,450,650,450,650,500,650,450,650,450,650,450,700,450,650,450,650,1550,650,1600,650,1550,650,1600,650,1550,650};
//unsigned int samsungTVVolDown[68] = {4500,4400,650,1600,600,1650,600,1600,600,500,650,500,600,500,600,500,650,450,650,1600,650,1600,600,1600,600,500,650,500,600,500,600,500,650,450,650,1600,600,1650,600,500,600,1600,650,500,600,500,600,500,650,500,600,500,600,500,600,1650,600,500,600,1600,650,1600,600,1650,600,1600,600};
//unsigned int samsungTVChUp[68] = {4500,4450,600,1650,600,1600,600,1650,600,500,600,500,600,550,600,500,600,500,600,1650,600,1600,600,1650,600,500,600,500,600,550,600,500,600,500,600,500,600,1650,600,500,600,500,650,1600,600,500,600,550,600,500,600,1600,650,500,600,1600,600,1650,600,500,600,1600,650,1600,600,1650,600};
//unsigned int samsungTVChDown[68] = {4550,4400,650,1550,650,1600,650,1600,650,450,650,450,650,450,650,500,650,450,650,1550,650,1600,650,1550,700,450,650,450,650,450,650,500,650,450,650,450,700,400,700,450,650,450,650,1600,650,450,650,450,650,450,650,1600,650,1550,650,1600,650,1550,700,450,650,1550,650,1600,650,1550,650};
//unsigned int samsungTVMute[68] = {4500,4450,600,1650,600,1600,600,1650,600,500,650,500,600,500,600,500,600,500,600,1650,600,1600,600,1650,600,500,600,500,650,500,600,500,600,500,600,1650,600,1600,600,1650,600,1600,650,500,600,500,600,500,650,500,600,500,600,500,600,500,650,500,600,1600,600,1650,600,1600,600,1650,600};
//unsigned int samsungTVPrevCh[68] = {4500,4450,600,1600,650,1600,600,1650,600,500,600,500,650,450,650,500,600,500,600,1600,650,1600,600,1650,600,500,600,500,650,450,650,500,600,500,600,1600,650,1600,600,500,650,500,600,1600,650,450,650,500,600,500,600,500,650,450,600,1650,600,1650,600,500,600,1600,650,1600,600,1600,600};
//unsigned int samsungTVSource[68] = {4500,4450,600,1650,600,1600,600,1650,600,500,600,500,650,450,650,500,600,500,600,1650,600,1600,600,1650,600,500,600,550,600,500,600,500,600,500,600,1650,600,500,600,550,600,500,600,500,600,500,600,550,600,500,600,500,600,1600,600,1650,600,1600,650,1600,600,1650,600,1650,550,1650,600};
/*
* IRremote
* Version 0.1 July, 2009
* Copyright 2009 Ken Shirriff
* For details, see http://arcfn.com/2009/08/multi-protocol-infrared-remote-library.htm http://arcfn.com
* Edited by Mitra to add new controller SANYO
*
* Interrupt code based on NECIRrcv by Joe Knapp
* http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1210243556
* Also influenced by http://zovirl.com/2008/11/12/building-a-universal-remote-with-an-arduino/
*
* JVC and Panasonic protocol added by Kristian Lauszus (Thanks to zenwheel and other people at the original blog post)
* LG added by Darryl Smith (based on the JVC protocol)
* Whynter A/C ARC-110WD added by Francesco Meschia
*/
#ifndef IRremote_h
#define IRremote_h
// The following are compile-time library options.
// If you change them, recompile the library.
// If DEBUG is defined, a lot of debugging output will be printed during decoding.
// TEST must be defined for the IRtest unittests to work. It will make some
// methods virtual, which will be slightly slower, which is why it is optional.
//#define DEBUG
// #define TEST
// Results returned from the decoder
class decode_results {
public:
int decode_type; // NEC, SONY, RC5, UNKNOWN
union { // This is used for decoding Panasonic and Sharp data
unsigned int panasonicAddress;
unsigned int sharpAddress;
};
unsigned long value; // Decoded value
int bits; // Number of bits in decoded value
volatile unsigned int *rawbuf; // Raw intervals in .5 us ticks
int rawlen; // Number of records in rawbuf.
};
// Values for decode_type
#define NEC 1
#define SONY 2
#define RC5 3
#define RC6 4
#define DISH 5
#define SHARP 6
#define PANASONIC 7
#define JVC 8
#define SANYO 9
#define MITSUBISHI 10
#define SAMSUNG 11
#define LG 12
#define WHYNTER 13
#define UNKNOWN -1
// Decoded value for NEC when a repeat code is received
#define REPEAT 0xffffffff
// main class for receiving IR
class IRrecv
{
public:
IRrecv(int recvpin);
void blink13(int blinkflag);
int decode(decode_results *results);
void enableIRIn();
void resume();
private:
// These are called by decode
int getRClevel(decode_results *results, int *offset, int *used, int t1);
long decodeNEC(decode_results *results);
long decodeSony(decode_results *results);
long decodeSanyo(decode_results *results);
long decodeMitsubishi(decode_results *results);
long decodeRC5(decode_results *results);
long decodeRC6(decode_results *results);
long decodePanasonic(decode_results *results);
long decodeLG(decode_results *results);
long decodeJVC(decode_results *results);
long decodeSAMSUNG(decode_results *results);
long decodeWhynter(decode_results *results);
long decodeHash(decode_results *results);
int compare(unsigned int oldval, unsigned int newval);
} ;
// Only used for testing; can remove virtual for shorter code
#ifdef TEST
#define VIRTUAL virtual
#else
#define VIRTUAL
#endif
class IRsend
{
public:
IRsend() {}
void sendWhynter(unsigned long data, int nbits);
void sendNEC(unsigned long data, int nbits);
void sendSony(unsigned long data, int nbits);
// Neither Sanyo nor Mitsubishi send is implemented yet
// void sendSanyo(unsigned long data, int nbits);
// void sendMitsubishi(unsigned long data, int nbits);
void sendRaw(unsigned int buf[], int len, int hz);
void sendRC5(unsigned long data, int nbits);
void sendRC6(unsigned long data, int nbits);
void sendDISH(unsigned long data, int nbits);
void sendSharp(unsigned int address, unsigned int command);
void sendSharpRaw(unsigned long data, int nbits);
void sendPanasonic(unsigned int address, unsigned long data);
void sendJVC(unsigned long data, int nbits, int repeat); // *Note instead of sending the REPEAT constant if you want the JVC repeat signal sent, send the original code value and change the repeat argument from 0 to 1. JVC protocol repeats by skipping the header NOT by sending a separate code value like NEC does.
// private:
void sendSAMSUNG(unsigned long data, int nbits);
void enableIROut(int khz);
VIRTUAL void mark(int usec);
VIRTUAL void space(int usec);
} ;
// Some useful constants
#define USECPERTICK 50 // microseconds per clock interrupt tick
#define RAWBUF 100 // Length of raw duration buffer
// Marks tend to be 100us too long, and spaces 100us too short
// when received due to sensor lag.
#define MARK_EXCESS 100
#endif
/* This header file is part of the ATMEL AVR-UC3-SoftwareFramework-1.7.0 Release */
/*This file is prepared for Doxygen automatic documentation generation.*/
/*! \file *********************************************************************
*
* \brief SPI driver for AVR32 UC3.
*
* This file defines a useful set of functions for the SPI interface on AVR32
* devices.
*
* - Compiler: IAR EWAVR32 and GNU GCC for AVR32
* - Supported devices: All AVR32 devices with an SPI module can be used.
* - AppNote:
*
* \author Atmel Corporation: http://www.atmel.com \n
* Support and FAQ: http://support.atmel.no/
*
******************************************************************************/
/* Copyright (c) 2009 Atmel Corporation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. The name of Atmel may not be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* 4. This software may only be redistributed and used in connection with an Atmel
* AVR product.
*
* THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE
*
*/
#ifndef _SPI_H_
#define _SPI_H_
#include <avr32/io.h>
//! Time-out value (number of attempts).
#define SPI_TIMEOUT 10000
//! Status codes used by the SPI driver.
typedef enum
{
SPI_ERROR = -1,
SPI_OK = 0,
SPI_ERROR_TIMEOUT = 1,
SPI_ERROR_ARGUMENT,
SPI_ERROR_OVERRUN,
SPI_ERROR_MODE_FAULT,
SPI_ERROR_OVERRUN_AND_MODE_FAULT
} spi_status_t;
//! Option structure for SPI channels.
typedef struct
{
//! The SPI channel to set up.
unsigned char reg;
//! Preferred baudrate for the SPI.
unsigned int baudrate;
//! Number of bits in each character (8 to 16).
unsigned char bits;
//! Delay before first clock pulse after selecting slave (in PBA clock periods).
unsigned char spck_delay;
//! Delay between each transfer/character (in PBA clock periods).
unsigned char trans_delay;
//! Sets this chip to stay active after last transfer to it.
unsigned char stay_act;
//! Which SPI mode to use when transmitting.
unsigned char spi_mode;
//! Disables the mode fault detection.
//! With this bit cleared, the SPI master mode will disable itself if another
//! master tries to address it.
unsigned char modfdis;
} spi_options_t;
/*! \brief Resets the SPI controller.
*
* \param spi Base address of the SPI instance.
*/
extern void spi_reset(volatile avr32_spi_t *spi);
/*! \brief Initializes the SPI in slave mode.
*
* \param spi Base address of the SPI instance.
* \param bits Number of bits in each transmitted character (8 to 16).
* \param spi_mode Clock polarity and phase.
*
* \return Status.
* \retval SPI_OK Success.
* \retval SPI_ERROR_ARGUMENT Invalid argument(s) passed.
*/
extern spi_status_t spi_initSlave(volatile avr32_spi_t *spi,
unsigned char bits,
unsigned char spi_mode);
/*! \brief Sets up the SPI in a test mode where the transmitter is connected to
* the receiver (local loopback).
*
* \param spi Base address of the SPI instance.
*
* \return Status.
* \retval SPI_OK Success.
*/
extern spi_status_t spi_initTest(volatile avr32_spi_t *spi);
/*! \brief Initializes the SPI in master mode.
*
* \param spi Base address of the SPI instance.
* \param options Pointer to a structure containing initialization options.
*
* \return Status.
* \retval SPI_OK Success.
* \retval SPI_ERROR_ARGUMENT Invalid argument(s) passed.
*/
extern spi_status_t spi_initMaster(volatile avr32_spi_t *spi, const spi_options_t *options);
/*! \brief Sets up how and when the slave chips are selected (master mode only).
*
* \param spi Base address of the SPI instance.
* \param variable_ps Target slave is selected in transfer register for every
* character to transmit.
* \param pcs_decode The four chip select lines are decoded externally. Values
* 0 to 14 can be given to \ref spi_selectChip.
* \param delay Delay in PBA periods between chip selects.
*
* \return Status.
* \retval SPI_OK Success.
* \retval SPI_ERROR_ARGUMENT Invalid argument(s) passed.
*/
extern spi_status_t spi_selectionMode(volatile avr32_spi_t *spi,
unsigned char variable_ps,
unsigned char pcs_decode,
unsigned char delay);
/*! \brief Selects slave chip.
*
* \param spi Base address of the SPI instance.
* \param chip Slave chip number (normal: 0 to 3, extarnally decoded signal: 0
* to 14).
*
* \return Status.
* \retval SPI_OK Success.
* \retval SPI_ERROR_ARGUMENT Invalid argument(s) passed.
*/
extern spi_status_t spi_selectChip(volatile avr32_spi_t *spi, unsigned char chip);
/*! \brief Unselects slave chip.
*
* \param spi Base address of the SPI instance.
* \param chip Slave chip number (normal: 0 to 3, extarnally decoded signal: 0
* to 14).
*
* \return Status.
* \retval SPI_OK Success.
* \retval SPI_ERROR_TIMEOUT Time-out.
*
* \note Will block program execution until time-out occurs if last transmission
* is not complete. Invoke \ref spi_writeEndCheck beforehand if needed.
*/
extern spi_status_t spi_unselectChip(volatile avr32_spi_t *spi, unsigned char chip);
/*! \brief Sets options for a specific slave chip.
*
* The baudrate field has to be written before transfer in master mode. Four
* similar registers exist, one for each slave. When using encoded slave
* addressing, reg=0 sets options for slaves 0 to 3, reg=1 for slaves 4 to 7 and
* so on.
*
* \param spi Base address of the SPI instance.
* \param options Pointer to a structure containing initialization options for
* an SPI channel.
* \param pba_hz SPI module input clock frequency (PBA clock, Hz).
*
* \return Status.
* \retval SPI_OK Success.
* \retval SPI_ERROR_ARGUMENT Invalid argument(s) passed.
*/
extern spi_status_t spi_setupChipReg(volatile avr32_spi_t *spi,
const spi_options_t *options,
unsigned int pba_hz);
/*! \brief Enables the SPI.
*
* \param spi Base address of the SPI instance.
*/
extern void spi_enable(volatile avr32_spi_t *spi);
/*! \brief Disables the SPI.
*
* Ensures that nothing is transferred while setting up buffers.
*
* \param spi Base address of the SPI instance.
*
* \warning This may cause data loss if used on a slave SPI.
*/
extern void spi_disable(volatile avr32_spi_t *spi);
/*! \brief Tests if the SPI is enabled.
*
* \param spi Base address of the SPI instance.
*
* \return \c 1 if the SPI is enabled, otherwise \c 0.
*/
extern int spi_is_enabled(volatile avr32_spi_t *spi);
/*! \brief Checks if there is no data in the transmit register.
*
* \param spi Base address of the SPI instance.
*
* \return Status.
* \retval 1 No data in TDR.
* \retval 0 Some data in TDR.
*/
extern unsigned char spi_writeRegisterEmptyCheck(volatile avr32_spi_t *spi);
/*! \brief Writes one data word in master fixed peripheral select mode or in
* slave mode.
*
* \param spi Base address of the SPI instance.
* \param data The data word to write.
*
* \return Status.
* \retval SPI_OK Success.
* \retval SPI_ERROR_TIMEOUT Time-out.
*
* \note Will block program execution until time-out occurs if transmitter is
* busy and transmit buffer is full. Invoke
* \ref spi_writeRegisterEmptyCheck beforehand if needed.
*
* \note Once the data has been written to the transmit buffer, the end of
* transmission is not waited for. Invoke \ref spi_writeEndCheck if
* needed.
*/
extern spi_status_t spi_write(volatile avr32_spi_t *spi, unsigned short data);
/*! \brief Selects a slave in master variable peripheral select mode and writes
* one data word to it.
*
* \param spi Base address of the SPI instance.
* \param data The data word to write.
* \param pcs Slave selector (bit 0 -> nCS line 0, bit 1 -> nCS line 1,
* etc.).
* \param lastxfer Boolean indicating whether this is the last data word
* transfer.
*
* \return Status.
* \retval SPI_OK Success.
* \retval SPI_ERROR_TIMEOUT Time-out.
* \retval SPI_ERROR_ARGUMENT Invalid argument(s) passed.
*
* \note Will block program execution until time-out occurs if transmitter is
* busy and transmit buffer is full. Invoke
* \ref spi_writeRegisterEmptyCheck beforehand if needed.
*
* \note Once the data has been written to the transmit buffer, the end of
* transmission is not waited for. Invoke \ref spi_writeEndCheck if
* needed.
*/
extern spi_status_t spi_variableSlaveWrite(volatile avr32_spi_t *spi,
unsigned short data,
unsigned char pcs,
unsigned char lastxfer);
/*! \brief Checks if all transmissions are complete.
*
* \param spi Base address of the SPI instance.
*
* \return Status.
* \retval 1 All transmissions complete.
* \retval 0 Transmissions not complete.
*/
extern unsigned char spi_writeEndCheck(volatile avr32_spi_t *spi);
/*! \brief Checks if there is data in the receive register.
*
* \param spi Base address of the SPI instance.
*
* \return Status.
* \retval 1 Some data in RDR.
* \retval 0 No data in RDR.
*/
extern unsigned char spi_readRegisterFullCheck(volatile avr32_spi_t *spi);
/*! \brief Reads one data word in master mode or in slave mode.
*
* \param spi Base address of the SPI instance.
* \param data Pointer to the location where to store the received data word.
*
* \return Status.
* \retval SPI_OK Success.
* \retval SPI_ERROR_TIMEOUT Time-out.
*
* \note Will block program execution until time-out occurs if no data is
* received or last transmission is not complete. Invoke
* \ref spi_writeEndCheck or \ref spi_readRegisterFullCheck beforehand if
* needed.
*/
extern spi_status_t spi_read(volatile avr32_spi_t *spi, unsigned short *data);
/*! \brief Gets status information from the SPI.
*
* \param spi Base address of the SPI instance.
*
* \return Status.
* \retval SPI_OK Success.
* \retval SPI_ERROR_OVERRUN Overrun error.
* \retval SPI_ERROR_MODE_FAULT Mode fault (SPI addressed as slave
* while in master mode).
* \retval SPI_ERROR_OVERRUN_AND_MODE_FAULT Overrun error and mode fault.
*/
extern unsigned char spi_getStatus(volatile avr32_spi_t *spi);
#endif // _SPI_H_
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment