/**
 * Very simple modem implementation that sends MSD bytes from the IVS to the
 * PSAP by copying them directly into audio frames. This only works when the
 * channel block is configured to pass frames through unmodified.
 *
 * @copyright 2008, Research In Motion Ltd.
 *
 * @version $Id: //depot/main/dsp/ecall/c/testlab/modem_demo.c#3 $
 */

#include "modem.h"
#include "audio.h"

typedef enum {
    IvsIdle,
    IvsSendN,
    IvsSendMsd
} IvsState;

typedef struct {
    int state;
    int n;
    Ord8 msd[MSD_MAX_LENGTH];
    int index;
} IvsData;

typedef enum {
    PsapIdle,
    PsapStartTx,
    PsapActive,
} PsapState;

typedef struct {
    int  state;
    int  n;
    int  index;
    Ord8 msd[MSD_MAX_LENGTH];
} PsapData;

static IvsData ivs;
static PsapData psap;

void IvsReset(const Ord8 *msd, int length) {
    ivs.state = IvsIdle;
    ivs.index = 0;
    ivs.n = length;
    memcpy(ivs.msd, msd, length);
}

void IvsProcess(Int16 *pcm) {
    /* Run receiver */
    if (pcm[0] > 0) {
        ivs.state = IvsSendN;
    }

    /* Run the transmitter */
    memset(pcm, 0, PCM_LENGTH);
    if (ivs.state == IvsIdle) {
        /* Do nothing */
    }
    else if (ivs.state == IvsSendN) {
        pcm[0] = 1;
        pcm[1] = ivs.n;
        ivs.state = IvsSendMsd;
        ivs.index = 0;
    }
    else if (ivs.state == IvsSendMsd) {
        if (ivs.index < ivs.n) {
            pcm[0] = 2;
            pcm[1] = ivs.msd[ivs.index];
            ivs.index += 1;
        }
        else {
            /* Do nothing */
        }
    }
}

void PsapReset(void) {
    psap.n = 0;
    psap.index = 0;
    psap.state = PsapIdle;
}

void PsapSendStart(void) {
    psap.state = PsapStartTx;
}

void PsapProcess(Int16 *pcm) {
    /* Run the receiver */
    switch (psap.state) {
        case PsapIdle:
        case PsapStartTx:
            /* do nothing */
            break;
        case PsapActive:
            if (pcm[0] == 1) {
                psap.n = pcm[1];
            }
            else if (pcm[0] == 2) {
                if (psap.index < psap.n) {
                    psap.msd[psap.index] = pcm[1];
                    psap.index += 1;
                    if (psap.index >= psap.n) {
                        PsapReceiveMsd(psap.msd, psap.n);
                        PsapReset();
                    }
                }
            }
            break;
    }

    /* Run the transmitter */
    memset(pcm, 0, sizeof(PCM_LENGTH));
    if (psap.state == PsapStartTx) {
        pcm[0] = 1;
        psap.state = PsapActive;
    }
}
