The iPod controller that I submitted for the mbed challenge
Dependencies: mbed Motordriver PID
Diff: main.cpp
- Revision:
- 0:371773dd3dd1
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Wed May 04 15:41:13 2011 +0000 @@ -0,0 +1,170 @@ +#include "mbed.h" +#include "fader.h" +#include "MCP23017.h" +#include "TextLCD23017.h" +#include "keybrd.h" +#include "ipod.h" +#include "ipodcontrol.h" + +fader trackbar(p21,p22,p23,p20); +I2C iic(p28, p27); +MCP23017 ui(iic, 0x40); +TextLCD23017 lcd(ui); +keybrd kb(ui, p12);//second argument is the interrupt pin, although only used by keyboard it logically belongs to the MCP23017 +ipod pod(p9, p10);//serial pins for the ipod +ipodControl cntrl(pod); + +DigitalOut led(LED1);//for debug only + +const float beyondEnd = 2.0; //any number > 1.0 +float inmark=0, outmark=beyondEnd; + +void show(const char* s) { //write to LCD bottom line + lcd.locate(0, 1); + lcd.printf("%-16s", s); +} + +void showtop(const char* s) { //write to LCD top line + lcd.locate(0, 0); + lcd.printf("%-16s", s); +} + +void show(unsigned, const char* s) { + lcd.locate(0, 1); + if (cntrl.getItems()>0) + lcd.printf("%-16s", s); + else + lcd.printf(" <Empty> ");//placeholder +} + +void time(unsigned t) { //OnTime, iPod polling command + float pos = t; + unsigned length = cntrl.getTrackLength(); + if (length == 0) + return;//valid length not available (yet) + pos /= length; + if (pos >= outmark) { + cntrl.MoveTo(inmark * cntrl.getTrackLength()); + trackbar.set(inmark); + } else + trackbar.set(pos);//when fader is 'holding' or 'tracking moveto new position +} + +void changeTrack(unsigned t) { //OnTrackChange, iPod polling command + printf("Track %u\n", t); + //the track changed so we need new artist/song/tracklength + //must not call guarded_SendAirCmd here because the rx_buffer will not be released before reply arrives + //calling a sequence of normal SendAirCmds is also dangerous because they may not be properly queued + cntrl.Update(); //sends the first SendAirCmd and starts the 'updater' state-machine to send the rest +} + +void OnMove(float newpos) { //fader move command, called after manual movement of wiper + cntrl.MoveTo(newpos * cntrl.getTrackLength()); //new wiper position in ms +} + +void errHandler(unsigned e, unsigned cmd) { //ipodcontrol::OnError + if (e==1 && cmd==get_ipod_name) + lcd.printf("iPod connected??"); +} + +void handleKey(char c) { //handles the keys of the user interface + switch (c) { + case 1://OK + if (cntrl.getMode() == nav) + cntrl.OK(); + else { //mode==play + outmark = beyondEnd;//stop repeating marked section + inmark = 0; + } + break; + case 2://>>/out + if (cntrl.getMode()==nav) + cntrl.Fwd(); + else //'out' command + if (cntrl.getPos() > inmark) + outmark = cntrl.getPos(); + break; + case 3://<</in + if (cntrl.getMode()==nav) + cntrl.Rev(); + else //'in' command + if (cntrl.getPos() < outmark) + inmark = cntrl.getPos(); + break; + case 4://>|| + cntrl.PlayPause(); + break; + case 5://menu + cntrl.Menu(); + if (cntrl.getType() == top) + show(""); + break; + case 6://rec + case 7://replay + default: + break; + } +} + +/* On a real iPod, the wheel has multiple functions, depending on the mode: + navigation: moves up and down the current list + play: changes volume (not implemented here and afaik not possible) + but it has submodes + fast: moves quickly through a song (here implemented by fader movement) + stars: rates the song (not implemented) +*/ +int main() { + int count = 0; + iic.frequency(400000);//does not work, stays at 100kHz + cntrl.OnGetNames = show; + cntrl.OnTitle = show; + cntrl.OnArtist = showtop; + cntrl.OnAlbum = show; + cntrl.OnTime = time; + cntrl.OnTrackChange = changeTrack; + cntrl.OnError = errHandler; + trackbar.setOnMove(OnMove); + if (!cntrl.readName()) //calls errHandler if no reply + ; + wait(1.0); + cntrl.StartPolling(); + lcd.printf("%-16s", cntrl.getPathStr());//display "Playlist" on topline, bottomline empty + printf("entering main loop\n"); + for (;;) { + count = (count+1)%0x20000; + if (count==0) led = !led;//just to see if the main loop keeps running + + lcd.locate(0, 0);//col, row + + switch (kb.getevent(true)) { + case keybrd::keydown: + printf("Key %01d\n", kb.getc()); + handleKey(kb.getc()); + goto update; + case keybrd::keyup: + break; + case keybrd::posup://rotary encoder turns right + printf("Pos %d\n", kb.getpos()); + cntrl.Right(); + outmark = beyondEnd; //stop repeating + inmark = 0; + goto update; + case keybrd::posdown: + printf("Pos %d\n", kb.getpos()); + cntrl.Left(); + outmark = beyondEnd; //stop repeating + inmark = 0; +update: + if (cntrl.getType() == top) + lcd.printf("%-16s", cntrl.getPathStr());//toplevel name from array + else + lcd.printf("%-16s", cntrl.getTypeStr());//item name from iPod + break; + case keybrd::none: + break; + default: + printf("Unknown keyboard event\n"); + } + cntrl.poll();//handle the ipodcontrol events in the event loop + } +}