/* ECE 476 Final Project
* Austin S. Lu & Albert Ren
* asl45 awr8
*/
#include <mega32.h>
#include <stdio.h>
#include <stdlib.h> //for ltoa
#include <delay.h>
#asm
.equ __lcd_port=0x15
#endasm
#include <lcd.h>
//Bruce's definitions
#define begin {
#define end }
//Define the states for the state machine
#define Command 0
#define DecodeCommand 1
#define Send 2
#define button_release 3
#define hold 4
#define Receive 5
int state = 0;
//Define the commands we support
//MODE 2 iPod Remote Functions
#define play 0x01
#define volup 0x02
#define voldown 0x04
#define skipfwd 0x08
#define skipback 0x10
#define menu 0x40
#define select 0x80
//MODE 4 Advanced Remote
#define type 0x12
#define name 0x14
#define current 0x1e
#define title 0x20
#define artist 0x22
#define album 0x24
//MODE 4 Send Commands
#define Switch 0
#define GetTrack 1
#define UseTrack 2
#define SwitchtoMode2 3
#define SendPlay 4
//Information on the Apple Accessory Protocol can be found at
// http://ipodlinux.org/Apple_Accessory_Protocol
//Here are some variables that we'll need
char mstime = 0;
char header1 = 0xff;
char header2 = 0x55;
char length;
char mode=0x02;
char command[2];
int checksum;
int index = 0;
int debouncecounter = 0;
char lastpress = 0;
char press = 0;
int timeout = 0;
unsigned long currentsong;
int param_length = 0;
//Here are the flags we're using
char validcommand = 0;
char commandtype = 0;
char stopflag = 0;
char releaseflag = 0;
char transmitdone_flag = 0;
char mode4flag = 0;
unsigned char switchmode[16] = {0xff, 0x55, 0x03, 0x00, 0x01, 0x04, 0xF8, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
unsigned char switchback[16] = {0xff, 0x55, 0x03, 0x00, 0x01, 0x02, 0xFA, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
unsigned char currenttrackcommand[16] = {0xff, 0x55, 0x03, 0x04, 0x00, 0x1E, 0xDB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
int tempchecksum;
unsigned char t_buffer_temp[16];
//For LCD displays
unsigned char lcdbuffer[50];
unsigned int lcdbufferlength = 16;
unsigned int lcdstart = 0;
int lcdtime = 0;
char hold_timer = 0;
int timeoutcounter = 0;
int failurecount = 0;
int mode4sequence = 0;
//variables we use for transmitting
unsigned char t_index; //current string index
unsigned char t_buffer[16]; //output string
unsigned char t_ready; //flag for transmit done
unsigned char t_char; //current character
//RXC ISR variables
unsigned char r_index=0; //current string index
unsigned char r_buffer[128]; //input string
unsigned char r_ready; //flag for receive done
unsigned char r_char; //current character
unsigned char r_checksum; //received checksum
unsigned char prev_char = 0;
unsigned char start_checksum = 0;
unsigned char r_length = 0xF5;
//Functions we use
void initialize(void);
void puts_int(void);
void buttons (void);
void gets_int(void);
void lcd_scroll(void);
//timer 0 overflow ISR
interrupt [TIM0_COMP] void timer0_overflow(void)
begin
mstime++;
lcdtime ++;
end
//UART xmit-empty ISR
//TRANSMITS LSB FIRST (Little Endian is stupid!)
//http://en.wikipedia.org/wiki/Serial_port
interrupt [USART_DRE] void uart_send(void)
{
t_index++;
t_char = t_buffer[t_index];
if(t_char == (char)checksum){//at this point, we know what the end is
UDR = t_char;
stopflag = 1;
stopflag = 0;
UCSRB.5=0; //kill isr
t_ready=1; //transmit done
checksum = 0;
}
else {UDR = t_char;} //send the char
}
//UART character-ready ISR
interrupt [USART_RXC] void uart_rec(void)
begin
r_char=UDR; //get a char
//build the input string
//iPod takes the form of 0xFF 0x55 Data Checksum
//We are assuming idle high, so we should check for 0x55 instead
if((r_char == (char)(r_checksum & 0xff)) && ((r_index-3)==r_length)) {
r_ready=1; //signal cmd processor
UCSRB.7=0; //stop rec ISR
start_checksum = 0;
}
if(start_checksum == 1) {
r_checksum = r_checksum - r_char;
}
if(r_char == 0x55 && prev_char == 0xff) {
start_checksum = 1;
r_checksum = 0x100;
}
r_buffer[r_index]=r_char;
if(r_index == 2) //Make the length so!
r_length = r_buffer[r_index];
r_index++;
prev_char = r_char;
end
void main(void)
begin
int k, temp, ReturnToSender;
unsigned char songnumber;
//State machine updates every ms for now
initialize();
while(1)
begin
if(lcdtime >= 300)
{
lcdtime = 0;
lcd_scroll();
}
if(mstime)
begin
buttons();
mstime = 0;
switch (state)
begin
case(Command):
//check if there's a command. If so, we will decode it
mode4sequence = Switch;
timeoutcounter = 0;
failurecount = 0;
if(validcommand == 1)
begin
validcommand = 0;
state = DecodeCommand;
end
if((releaseflag == 1) && (validcommand == 0) && (mode == 0x02)) //the button was released
begin
releaseflag = 0;
state = button_release;
end
break;
case(DecodeCommand):
//We must decode the command! If statements galore!
t_buffer[0] = header1; //0xff
t_buffer[1] = header2; //0x55
if((mode == 0x02) || (commandtype == current))
{
length = 0x03;
}
else
begin
length = 7; //Otherwise length is 7 bytes, cause it's a mode 4 command
end
t_buffer[2] = length;
t_buffer[3] = mode;
if(mode == 0x04)
{
mode4flag = 1;
}
t_buffer[4] = 0x00; //Beginning of command
if(commandtype == play)
t_buffer[5] = play;
if(commandtype == volup)
t_buffer[5] = volup;
if(commandtype == voldown)
t_buffer[5] = voldown;
if(commandtype == skipfwd)
t_buffer[5] = skipfwd;
if(commandtype == skipback)
t_buffer[5] = skipback;
if(commandtype == album)
t_buffer[5] = album;
if(commandtype == title)
t_buffer[5] = title;
if (commandtype == artist)
t_buffer[5] = artist;
if((mode == 0x04) && (commandtype != current)) //We need to send ipod the current song
begin
t_buffer[6] = (currentsong >> 24) & 0xff ; //& with 0xFF cause we're cautious people!
t_buffer[7] = (currentsong >> 16) & 0xff;
t_buffer[8] = (currentsong >> 8) & 0xff;
t_buffer[9] = currentsong & 0xff;
param_length = 4; //Mode 4 and Mode 2 have different lengths
end
for (index = 2; index < 6 + param_length; index ++) { //for checksum
checksum = checksum + t_buffer[index];
}
checksum = (0x100 - checksum & 0xff);
t_buffer[6+param_length] = (char) checksum & 0xff; //as a char */
param_length = 0; //We always reset to Mode 2 commands
state = Send;
break;
case(Send):
stopflag = 0;
timeoutcounter = 0;
- 1
- 2
前往页