Serial RAM (SPI SRAM) library 23K256, 23LC1024 (Microchip) see: http://mbed.org/users/okini3939/notebook/extend-memory/

Dependents:   SPIRAM_23LC1024_FIFO

CBuffer_SRAM.cpp

Committer:
okini3939
Date:
2013-03-08
Revision:
1:5a261b6a88af

File content as of revision 1:5a261b6a88af:

/* Copyright (C) 2012 mbed.org, MIT License
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
 * and associated documentation files (the "Software"), to deal in the Software without restriction,
 * including without limitation the rights to use, copy, modify, merge, publish, distribute,
 * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all copies or
 * substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */
/*
 * Modified by 2013 Hiroshi Suga, MIT License
 */
 
#include "CBuffer_SRAM.h"

#define DBG(...)
//#define DBG(...) printf("" __VA_ARGS__) 

CircBuffer::CircBuffer(int length) {
    _ram = SerRAM::getInstance();
    write = 0;
    read = 0;
    ram_addr = xalloc(length + 1);
    size = length + 1;
};

int CircBuffer::xalloc(int n) {
    static uint32_t ram_alloc = 0;
    uint32_t a;

    a = ram_alloc;
    ram_alloc += (n + WINDOW_SIZE - 1) & ~WINDOW_MASK;
    DBG("alloc %x ,next %x\r\n", a, ram_alloc);
    return a;
}

bool CircBuffer::isFull() {
    return (((write + 1) % size) == read);
};

bool CircBuffer::isEmpty() {
    return (read == write);
};

bool CircBuffer::queue(char k) {
    if (isFull()) {
        return false;
    }
#ifdef RAM_USE_DMA
    while (_ram->isBusy()) DBG("busy\r\n");
#endif
    uint32_t w = write;
    buf_w[w & WINDOW_MASK] = k;
    w = (w + 1) % size;
    if ((w & WINDOW_MASK) == 0) {
        _ram->write(ram_addr + (write & ~WINDOW_MASK), buf_w, WINDOW_SIZE, true);
        DBG("(W %x)\r\n", ram_addr + (write & ~WINDOW_MASK));
        if ((write & ~WINDOW_MASK) == (read & ~WINDOW_MASK)) {
            // w = r
            memcpy(buf_r, buf_w, WINDOW_SIZE);
            DBG("memcpy\r\n");
        }
    }
    write = w;
    return true;
}

void CircBuffer::flush() {
    _ram->write(ram_addr + (write & ~WINDOW_MASK), buf_w, WINDOW_SIZE, true);
    read = 0;
    write = 0;
}

uint32_t CircBuffer::available() {
    return (write >= read) ? write - read : size - read + write;
};

uint32_t CircBuffer::use() {
    return size - available() - 1;
};

bool CircBuffer::dequeue(char * c) {
    bool empty = isEmpty();
    if (!empty) {
#ifdef RAM_USE_DMA
        while (_ram->isBusy()) DBG("busy\r\n");
#endif
        uint32_t w = write, r = read;
        if ((w & ~WINDOW_MASK) == (r & ~WINDOW_MASK) && w > r) {
            *c = buf_w[r & WINDOW_MASK];
        } else {
            *c = buf_r[r & WINDOW_MASK];
        }
        r = (r + 1) % size;
        if ((r & WINDOW_MASK) == 0) {
            _ram->read(ram_addr + (r & ~WINDOW_MASK), buf_r, WINDOW_SIZE, true);
            DBG("(R %x)\r\n", (r & ~WINDOW_MASK));
        }
        read = r;
    }
    return (!empty);
};

void CircBuffer::dump() {
    int i;
    printf("buf_w\r\n");
    for (i = 0; i < WINDOW_SIZE; i ++) {
        printf(" %02x", buf_w[i]);
        if ((i & 0x0f) == 0x0f) printf("\r\n");
    }
    printf("buf_r\r\n");
    for (i = 0; i < WINDOW_SIZE; i ++) {
        printf(" %02x", buf_r[i]);
        if ((i & 0x0f) == 0x0f) printf("\r\n");
    }
}