#include <stdint.h>

#include "rpi-gpio.h"
#include "rpi-mailbox.h"


/* Mailbox 0 mapped to it's base address */
static mailbox_t* rpiMailbox0;

void RPI_Mailbox0Write( mailbox0_channel_t channel, int value )
{
    rpiMailbox0 = (mailbox_t*)RPI_MAILBOX0_BASE;
    /* For information about accessing mailboxes, see:
       https://github.com/raspberrypi/firmware/wiki/Accessing-mailboxes */

    /* Add the channel number into the lower 4 bits */
    value &= ~(0xF);
    value |= channel;

    /* Wait until the mailbox becomes available and then write to the mailbox
       channel */
    while( ( rpiMailbox0->Status & ARM_MS_FULL ) != 0 ) { }

    /* Write the modified value + channel number into the write register */
    rpiMailbox0->Write = value;
}


int RPI_Mailbox0Read( mailbox0_channel_t channel )
{
    rpiMailbox0 = (mailbox_t*)RPI_MAILBOX0_BASE;
    /* For information about accessing mailboxes, see:
       https://github.com/raspberrypi/firmware/wiki/Accessing-mailboxes */
    int value = -1;

    /* Keep reading the register until the desired channel gives us a value */
    while( ( value & 0xF ) != channel )
    {
        /* Wait while the mailbox is empty because otherwise there's no value
           to read! */
        while( rpiMailbox0->Status & ARM_MS_EMPTY ) { }

        /* Extract the value from the Read register of the mailbox. The value
           is actually in the upper 28 bits */
        value = rpiMailbox0->Read;
    }

    /* Return just the value (the upper 28-bits) */
    return value >> 4;
}

int RPI_Mailbox0Flush( mailbox0_channel_t channel )
{
   rpiMailbox0 = (mailbox_t*)RPI_MAILBOX0_BASE;
   int value = -1;

   while( !(rpiMailbox0->Status & ARM_MS_EMPTY) ) {
      value = rpiMailbox0->Read;
   }

    /* Return just the value (the upper 28-bits) */
    return value >> 4;
}
