#include "SEGGER_RTT.h"

#include <string.h>

static char _acUpBuffer[BUFFER_SIZE_UP];
static char _acDownBuffer[BUFFER_SIZE_DOWN];

SEGGER_RTT_CB _SEGGER_RTT = {
    "SEGGER RTT",
    SEGGER_RTT_MAX_NUM_UP_BUFFERS,
    SEGGER_RTT_MAX_NUM_DOWN_BUFFERS,
    {
        { "Terminal", _acUpBuffer, BUFFER_SIZE_UP, 0u, 0u, SEGGER_RTT_MODE_DEFAULT }
    },
    {
        { "Terminal", _acDownBuffer, BUFFER_SIZE_DOWN, 0u, 0u, SEGGER_RTT_MODE_DEFAULT }
    }
};

void SEGGER_RTT_Init(void)
{
    memset(&_SEGGER_RTT, 0, sizeof(_SEGGER_RTT));
    memcpy(_SEGGER_RTT.acID, "SEGGER RTT", 10);
    _SEGGER_RTT.MaxNumUpBuffers = SEGGER_RTT_MAX_NUM_UP_BUFFERS;
    _SEGGER_RTT.MaxNumDownBuffers = SEGGER_RTT_MAX_NUM_DOWN_BUFFERS;
    _SEGGER_RTT.aUp[0].sName = "Terminal";
    _SEGGER_RTT.aUp[0].pBuffer = _acUpBuffer;
    _SEGGER_RTT.aUp[0].SizeOfBuffer = BUFFER_SIZE_UP;
    _SEGGER_RTT.aUp[0].Flags = SEGGER_RTT_MODE_DEFAULT;
    _SEGGER_RTT.aDown[0].sName = "Terminal";
    _SEGGER_RTT.aDown[0].pBuffer = _acDownBuffer;
    _SEGGER_RTT.aDown[0].SizeOfBuffer = BUFFER_SIZE_DOWN;
    _SEGGER_RTT.aDown[0].Flags = SEGGER_RTT_MODE_DEFAULT;
}

static void _EnsureInit(void)
{
    if (_SEGGER_RTT.acID[0] != 'S') {
        SEGGER_RTT_Init();
    }
}

unsigned SEGGER_RTT_Write(unsigned BufferIndex, const void *pBuffer, unsigned NumBytes)
{
    SEGGER_RTT_BUFFER_UP *ring;
    const char *data = (const char *)pBuffer;
    unsigned i;

    _EnsureInit();
    if (BufferIndex >= (unsigned)_SEGGER_RTT.MaxNumUpBuffers) {
        return 0u;
    }

    ring = &_SEGGER_RTT.aUp[BufferIndex];
    for (i = 0; i < NumBytes; ++i) {
        unsigned next = (ring->WrOff + 1u) % ring->SizeOfBuffer;
        if (next == ring->RdOff) {
            break;
        }
        ring->pBuffer[ring->WrOff] = data[i];
        ring->WrOff = next;
    }

    return i;
}

unsigned SEGGER_RTT_WriteString(unsigned BufferIndex, const char *s)
{
    return SEGGER_RTT_Write(BufferIndex, s, (unsigned)strlen(s));
}

unsigned SEGGER_RTT_PutChar(unsigned BufferIndex, char c)
{
    return SEGGER_RTT_Write(BufferIndex, &c, 1u);
}
