The iPod controller that I submitted for the mbed challenge

Dependencies:   mbed Motordriver PID

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
+    }
+}