1
0
mirror of https://github.com/DanielBroad/AVCSniffer synced 2025-06-07 07:56:29 +00:00
AVCSniffer/ipod.c
2013-02-17 17:57:34 +00:00

599 lines
13 KiB
C
Executable File

/*
Copyright (C) 2006 Daniel Broad <daniel@dorada.co.uk>.
-----------------------------------------------------------------------
this file is a part of the Lexus iPod Project
-----------------------------------------------------------------------
http://www.lexusipod.com
*/
#include "com232.h"
#include "ipod.h"
#include "avclandrv.h"
#include "inputoutput.h"
#include "delay.h"
#include <avr/io.h>
#include <avr/pgmspace.h>
//lingo commands Len
const u08 cmLingo[] PROGMEM = {0x03, 0x00, 0x01, 0x04};
const u08 cmPlayPause[] PROGMEM = {0x04, 0x04, 0x00, 0x29, 0x01};
const u08 cmstop[] PROGMEM = {0x04, 0x04, 0x00, 0x29, 0x02};
const u08 cmPollingOn[] PROGMEM = {0x04, 0x04, 0x00, 0x26, 0x01};
const u08 cmSkipTrackF[]PROGMEM = {0x04, 0x04, 0x00, 0x29, 0x03};
const u08 cmSkipTrackR[]PROGMEM = {0x04, 0x04, 0x00, 0x29, 0x04};
const u08 cmFF[] PROGMEM = {0x04, 0x04, 0x00, 0x29, 0x05};
const u08 cmRR[] PROGMEM = {0x04, 0x04, 0x00, 0x29, 0x06};
const u08 cmResume[] PROGMEM = {0x04, 0x04, 0x00, 0x29, 0x07};
const u08 cmPlaylistPos[] PROGMEM = {0x03, 0x04, 0x00, 0x1E};
const u08 cmExecSwitch[] PROGMEM = {0x07, 0x04, 0x00, 0x28,0x00,0x00,0x00,0x01};
const u08 cmPlaylistCount[] PROGMEM = {0x04, 0x04, 0x00, 0x18, 0x01};
const u08 cmGetShuffle[] PROGMEM = {0x03, 0x04, 0x00, 0x2C};
const u08 cmGetRepeat[] PROGMEM = {0x03, 0x04, 0x00, 0x2F};
const u08 cmGetTimeStatus[] PROGMEM = {0x03, 0x04, 0x00, 0x1C};
u08 cmShuffle[] = {0x04, 0x04, 0x00, 0x2E, 0x00};
u08 cmRepeat[] = {0x04, 0x04, 0x00, 0x31, 0x00};
u08 cmPlaylistSwitch[] = {0x08, 0x04, 0x00, 0x17, 0x01, 0x00,0x00,0x00,0x00};
//lingo replies
#define rpNumplaylists 0x19
#define rpTimeStatusInfo 0x1D
#define rpPlaylistPosition 0x1F
#define rpSongTime 0x27
#define rpACK 0x01
#define rpTimeStatus 0x1D
#define rpShuffleStatus 0x2D
#define rpRepeatMode 0x30
//------------------------------------------------------------------------------
void AddBuffer(u08 tmp)
{
if (RxCharEnd<15) {
RxBuffer[RxCharEnd] = tmp; // Store received character
};
RxCharEnd++;
}
//------------------------------------------------------------------------------
void ClearInBuffer()
{
u08 i;
for (i=0;i<15;i++)
{
RxBuffer[i] = 0x00;
};
RxCharEnd=0;
}
//------------------------------------------------------------------------------
#ifndef MONITOR
void RS232_LINGO(u08* pBuf)
{
// output a lingo message
register u08 c;
u08 i = 1;
while (i<=pBuf[0])
{
c = pBuf[i];
RS232_SendByte(c);
i++;
}
}
#endif
//------------------------------------------------------------------------------
#ifdef MONITOR
void RS232_LINGO_TEST(u08* pBuf)
{
// test output a lingo message to pc on rs232
register u08 c;
u08 i = 1;
while (i<=pBuf[0])
{
c = pBuf[i];
RS232_PrintHex8(c);
i++;
}
RS232_SendByte('\r');
RS232_SendByte('\n');
}
#endif
//------------------------------------------------------------------------------
#ifndef MONITOR
void RS232_LINGO_P(u08* pBuf)
{
// output a lingo message
register u08 c;
u08 i = 1;
u08 length = pgm_read_byte(pBuf);
while (i<=length)
{
c = pgm_read_byte(pBuf+i);
RS232_SendByte(c);
i++;
}
}
#endif
//------------------------------------------------------------------------------
#ifdef MONITOR
void RS232_LINGO_TEST_P(u08* pBuf)
{
// test output a lingo message to pc on rs232
register u08 c;
u08 i = 1;
u08 length = pgm_read_byte(pBuf);
while (i<=length)
{
c = pgm_read_byte(pBuf+i);
RS232_PrintHex8(c);
i++;
}
RS232_SendByte('\r');
RS232_SendByte('\n');
}
#endif
//------------------------------------------------------------------------------
void iPod_Poll()
{
// check to see if we have an ipod message waiting to be processed
if (RXState == RX_FINISHED)
iPod_ProcessResponse();
// check if iPod connected, set lingo mode
if (IPOD_IS_CONNECTED!=iPodConnected)
{
iPodConnected = IPOD_IS_CONNECTED;
if (iPodConnected)
{
delay_ms(50);
iPod(cmdLingo);
delay_ms(50);
iPodEvent = evPlaylistCount;
RXState = WAITING_FOR_FF;
iPodMode = stStop;
AuxInput = 1;
SwitchInputs();
}
else
{
// switchinputs knows its not connected so will switch to aux2
SwitchInputs();
}
};
// if we need to sync car play/pause state to ipod
if ((CD_Mode != iPodMode) & (AuxInput == 0))
{
switch (CD_Mode) {
case stStop:
case stPlay:
if ((iPodMode == stFF) | (iPodMode == stRR))
iPod(cmdResume);
else
iPod(cmdPlay);
break;
case stFF:
iPod(cmdFF);
break;
case stRR:
iPod(cmdRR);
break;
default:
break;
};
iPodMode = CD_Mode;
};
// other input, iPod should be stop
if (AuxInput == 1)
if (iPodMode != stStop)
{
if (iPodConnected) iPod(cmdPlay);
iPodMode = stStop;
iPodEvent = evTimeStatus;
}
// do iPod events
if (iPodConnected)
{
#ifdef MONITOR
if (iPodEvent != evNone)
{
RS232_Print("iPod Event:");
RS232_PrintHex8(iPodEvent);
RS232_Print("\r\n");
};
#endif
switch (iPodEvent) {
case evPlaylistPosition:
iPod(cmdPlayListPosition);
iPodEvent = evNone;
break;
case evPlayListOne:
iPod(cmdPlayListOne);
iPodEvent = evPlaylistPosition;
iPodPlaylist = 1;
iPodMode = stPlay;
break;
case evPlaylistCount:
iPod(cmdNumPlaylists);
iPodEvent = evPlaylistPosition;
break;
case evTimeStatus:
iPod(cmdTimeStatus);
iPodEvent = evPlaylistPosition;
default:
if (randomMode != iPodShuffle)
{
iPod(cmdShuffle);
iPodShuffle = randomMode;
} else {
if (repeatMode != iPodRepeat)
{
iPod(cmdRepeat);
iPodRepeat = repeatMode;
};
};
#ifndef MONITOR
if ((maxDisc == 0))
iPodEvent = evPlaylistCount;
#endif
break;
};
}
// if RX error reset comms.
if (RXState == RX_ERROR) {
ClearInBuffer();
RXState = WAITING_FOR_FF;
UCSRB = UART_RXENABLE; //enable receiver
};
}
//------------------------------------------------------------------------------
void iPod_Data(u08 tmp) {
#ifdef MONITOR
{
RS232_PrintHex8(tmp);
RS232_Print("-");
RS232_PrintHex8(RXState);
RS232_Print("\n");
};
#endif
switch (RXState)
{
case WAITING_FOR_FF:
if( tmp == 0xFF )
RXState = WAITING_FOR_55;
break;
case WAITING_FOR_55:
if( tmp == 0x55 )
RXState = WAITING_FOR_LENGTH;
else
{
if (tmp == 0xFF)
RXState = WAITING_FOR_55;
else
RXState = RX_ERROR;
}
break;
case WAITING_FOR_LENGTH:
if (tmp > 15)
{
RXState = RX_ERROR;
break;
}
CheckSum = tmp;
Length = tmp;
BytesToGo = tmp;
RXState = GETTING_MESSAGE;
break;
case GETTING_MESSAGE:
CheckSum += tmp;
AddBuffer(tmp);
if( !--BytesToGo )
RXState = WAITING_FOR_CHECKSUM;
break;
case WAITING_FOR_CHECKSUM:
CheckSum = ( CheckSum ^ 0xff ) + 1;
if (tmp == CheckSum)
{
RXState = RX_FINISHED;
UCSRB = UART_RXDISABLE; //disable receiver
}
else
{
RXState = RX_ERROR;
}
break;
case RX_FINISHED:
break;
case RX_ERROR:
UCSRB = UART_RXDISABLE; //disable receiver
break;
default:
#ifdef MONITOR
RS232_Print("Error\n");
#endif
RXState = RX_ERROR;
}
}
//------------------------------------------------------------------------------
void iPod_ProcessResponse()
{ // 04 00 XX ......
uint32_t temp = 0;
#ifdef MONITOR
RS232_PrintHex8(RxBuffer[2]);
RS232_SendByte('\r');
RS232_SendByte('\n');
#endif
switch (RxBuffer[2]) {
case rpACK:
break;
case rpNumplaylists:
temp = RxBuffer[5];
temp = temp << 8;
temp = RxBuffer[6];
temp = temp + 1;
maxDisc = temp;
if (maxDisc > 99) maxDisc = 99;
Event |= EV_DISPLAY;
break;
case rpSongTime:
if (RxBuffer[4] == 0xFF)
{
// We are not playing
iPodEvent = evTimeStatus;
}
else
{
iPod_SetTime(RxBuffer[4], RxBuffer[5], RxBuffer[6], RxBuffer[7]);
}
break;
case rpPlaylistPosition:
if (RxBuffer[3] == 0xFF)
{
// We are not playing?
iPodEvent = evTimeStatus;
}
else
{
temp = RxBuffer[4];
temp = temp << 8;
temp += RxBuffer[5];
temp = temp << 8;
temp += RxBuffer[6];
temp++;
temp = temp % 100;
if (AuxInput == 0)
cd_Track = BCDu08(temp);
}
iPodTrack = BCDu08(temp);
break;
case rpTimeStatus:
iPod_SetTime(RxBuffer[7], RxBuffer[8], RxBuffer[9], RxBuffer[10]);
switch (RxBuffer[11])
{
case 0x00:
iPodEvent = evPlayListOne;
break;
case 0x01:
iPodMode = stPlay;
break;
case 0x02:
iPodMode = stStop;
break;
};
break;
case rpShuffleStatus:
iPodShuffle = RxBuffer[3];
break;
case rpRepeatMode:
iPodRepeat = RxBuffer[3];
break;
default:
break;
}
// reset ready to go again
ClearInBuffer();
RXState = WAITING_FOR_FF;
UCSRB = UART_RXENABLE; //enable receiver
}
//------------------------------------------------------------------------------
void iPod_SendCommand(u08* command, u08 progmem)
{
u08 CheckSum = 0;
u08 length;
u08 i;
if (progmem)
length = pgm_read_byte(command);
else
length = command[0];
u08 begin[] = {0x03,0xFF,0x55,0x00};
u08 checksum[] = {0x01, 0xFF};
begin[3] = length;
// calc checksum
for (i=0;i<=length;i++)
{
if (progmem)
CheckSum += pgm_read_byte(command+i);
else
CheckSum += command[i];
};
CheckSum = ( CheckSum ^ 0xff ) + 1;
checksum[1] = CheckSum;
#ifdef MONITOR
{
RS232_LINGO_TEST((u08*) begin);
if (progmem)
RS232_LINGO_TEST_P(command);
else
RS232_LINGO_TEST(command);
RS232_LINGO_TEST((u08*) checksum);
}
#else
{
RS232_LINGO((u08*) begin);
if (progmem)
RS232_LINGO_P(command);
else
RS232_LINGO(command);
RS232_LINGO((u08*) checksum);
}
#endif
}
//------------------------------------------------------------------------------
void iPod(u08 command)
{
#ifdef MONITOR
{
RS232_Print("iPod:");
RS232_PrintHex8(command);
RS232_Print("\r\n");
}
#endif
switch (command) {
case cmdLingo:
iPod_SendCommand((u08*) cmLingo,1);
delay_ms(100);
iPod_SendCommand((u08*) cmPollingOn,1);
delay_ms(100);
iPod_SendCommand((u08*) cmPlaylistCount,1);
break;
case cmdPlay:
iPod_SendCommand((u08*) cmPlayPause,1);
iPodEvent = evTimeStatus;
break;
case cmdStop:
break;
case cmdNumPlaylists:
iPod_SendCommand((u08*) cmPlaylistCount,1);
break;
case cmdPlaylist:
if (cd_Disc < maxDisc)
{
cmPlaylistSwitch[8] = cd_Disc-1;
iPod_SendCommand((u08*) cmPlaylistSwitch,0);
iPod_SendCommand((u08*) cmExecSwitch,1);
iPodPlaylist = cd_Disc;
};
iPodEvent = evPlaylistCount;
break;
case cmdNextTrack:
iPod_SendCommand((u08*) cmSkipTrackF,1);
iPodEvent = evPlaylistPosition;
break;
case cmdPrevTrack:
iPod_SendCommand((u08*) cmSkipTrackR,1);
iPodEvent = evPlaylistPosition;
break;
case cmdNextPlaylist:
break;
case cmdPrevPlaylist:
break;
case cmdFF:
iPod_SendCommand((u08*) cmFF,1);
break;
case cmdRR:
iPod_SendCommand((u08*) cmRR,1);
break;
case cmdPlayListPosition:
iPod_SendCommand((u08*) cmPlaylistPos,1);
break;
case cmdPlayListOne:
cmPlaylistSwitch[8] = 0x00;
iPod_SendCommand((u08*) cmPlaylistSwitch,0);
iPod_SendCommand((u08*) cmExecSwitch,1);
cd_Disc = 1;
iPodPlaylist = cd_Disc;
break;
case cmdShuffle:
cmShuffle[4] = randomMode;
iPod_SendCommand((u08*) cmShuffle,0);
break;
case cmdRepeat:
cmRepeat[4] = repeatMode;
iPod_SendCommand((u08*) cmRepeat,0);
break;
case cmdResume:
iPod_SendCommand((u08*) cmResume,1);
break;
case cmdTimeStatus:
iPod_SendCommand((u08*) cmGetTimeStatus,1);
break;
case cmdGetShuffle:
iPod_SendCommand((u08*) cmGetShuffle,1);
break;
case cmdGetRepeat:
iPod_SendCommand((u08*) cmGetRepeat,1);
break;
default:
break;
}
}
u08 BCDu08 (u08 inbyte)
{
u08 units = (inbyte % 10);
u08 tens = ((inbyte) / 10);
return (tens * 16) + units;
}
void iPod_Error()
{
RXState = RX_ERROR;
}
void iPod_Init()
{
RXState = WAITING_FOR_FF;
UCSRB = UART_RXENABLE; //enable receiver
iPodPlaylist = 1;
iPodTrack = 1;
//iPodConnected = 99;
}
void iPod_SetTime(u08 b1, u08 b2, u08 b3, u08 b4)
{
uint32_t temp = 0;
if (AuxInput == 1) return;
temp = b1;
temp = temp << 8;
temp = b2;
temp = temp << 8;
temp += b3;
temp = temp << 8;
temp += b4;
temp = temp / (uint32_t) 1000;
cd_Time_Min = BCDu08((temp / (uint32_t)60) % (uint32_t)100);
iPodMin = cd_Time_Min;
if (cd_Time_Sec != BCDu08(temp % (uint32_t)60))
{
cd_Time_Sec = BCDu08(temp % (uint32_t)60);
iPodEvent = evPlaylistPosition;
iPodSec = cd_Time_Sec;
Event |= EV_STATUS;
iPodMode = stPlay;
};
};