The iPod controller that I submitted for the mbed challenge

Dependencies:   mbed Motordriver PID

main.cpp

Committer:
networker
Date:
2011-05-04
Revision:
0:371773dd3dd1

File content as of revision 0:371773dd3dd1:

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