Vishal Talwar / mbipanel

Dependents:   mbipanel_serial_display

mbipanel.cpp

Committer:
indraastra
Date:
2012-05-18
Revision:
0:ef590f1e65c3
Child:
1:c25833f8da58

File content as of revision 0:ef590f1e65c3:

#include "mbed.h"
#include "mbipanel.h"

namespace mbipanel {

namespace cfg {
const int pixelcfg_proto2x2[4][4] = {
    {10, 11, 9, 8},   {6, 7, 5, 4},
    {14, 15, 13, 12}, {2, 3, 1, 0}
};
const int pixelcfg_large1x4[4][4] = {
    {10, 9, 11, 8}, {14, 13, 15, 12},
    {2, 1, 3, 0},   {6, 5, 7, 4}
};
}  // namespace cfg


namespace hardware {

MBI::MBI(const int pixelx, const int pixely, MBIModel model, const int pixelcfg[][4]) {
    pixelx_ = pixelx;
    pixely_ = pixely;
    model_ = model;
    pixelcfg_ = (const int*)pixelcfg;
}

Panel::Panel(const int mbix, const int mbiy, const MBI& mbicfg) {
    mbix_ = mbix;
    mbiy_ = mbiy;
    num_mbis_ = mbix * mbiy;
    mbicfg_ = &mbicfg;
}

int Panel::channel_idx(const int x, const int y, const Color color) const {
    int mbii = x / mbicfg_->pixelx_;
    int mbij = y / mbicfg_->pixely_;
    int pixeli = x % (mbicfg_->pixelx_);
    int pixelj = y % (mbicfg_->pixely_);
    return mbicfg_->channel_idx(pixeli, pixelj, color)*num_mbis_ +
           (num_mbis_ - (mbij*mbix_+mbii) - 1);
}

PanelGrid::PanelGrid(const int panelx, const int panely, const Panel& panelcfg) {
    panelx_ = panelx;
    panely_ = panely;
    num_panels_ = panelx * panely;
    panelcfg_ = &panelcfg;
}

int PanelGrid::channel_idx(const int x, const int y, const Color color) const {
    int pixelw = panelcfg_->mbicfg_->pixelx_ * panelcfg_->mbix_;
    int pixelh = panelcfg_->mbicfg_->pixely_ * panelcfg_->mbiy_;
    int paneli = x / pixelw;
    int panelj = y / pixelh;
    int pixeli = x % pixelw;
    int pixelj = y % pixelh;
    return panelcfg_->channel_idx(pixeli, pixelj, color)*num_panels_ +
           (num_panels_ - (panelj*panelx_+paneli) - 1);
}

}  // namespace hardware

void Display::set(const int x, const int y, const unsigned int r, const unsigned int g, const unsigned int b, const unsigned int w) {
    data_[gridcfg_->channel_idx(x, y, RED)] = r;
    data_[gridcfg_->channel_idx(x, y, GREEN)] = g;
    data_[gridcfg_->channel_idx(x, y, BLUE)] = b;
    data_[gridcfg_->channel_idx(x, y, WHITE)] = w;
}

int Display::get(const int x, const int y, Color color) {
    return data_[gridcfg_->channel_idx(x, y, color)];
}

void Display::draw() {
    // Update MBI data channel by channel.
    for (int c = 0; c < 16; ++c) {
        for (int m = 0; m < num_mbis_; ++m) {
            unsigned int data = data_[c * num_mbis_ + m] & bitmask_;

            // DEBUG
            //printf("data %u: %u\n", c * num_mbis_ + m, data);
            // END DEBUG

            // Shift 16 bits/channel/MBI in MSB first.
            for (int b = 15; b >= 0; --b) {
                // If we are on the last bit of a channel (data latch), or the
                // last 2 bits of a data frame (global latch), send the data
                // latch high.
                if ((m == num_mbis_ - 1) && ((c == 15 && b == 1) || b == 0)) {
                    *datalat_ = 1;
                }

                *datain_ = (data >> b) & 1;
                *dataclk_ = 1;
                // This is to keep the data clock speed < 25MHz.
                // Without this delay, display behavior becomes erratic.
                wait_us(1);
                *dataclk_ = 0;
                wait_us(1);

                if ((m == num_mbis_ - 1) && b == 0) {
                    *datalat_ = 0;
                }
            }
        }
    }
}

void Display::configure(unsigned int cfg_packet) {
    for (int m = 0; m < num_mbis_; ++m) {
        // Shift 16 bits/channel/MBI in MSB first.
        for (int b = 15; b >= 0; --b) {
            // If we are on the last 10 bits of the configuration packet, send
            // latch high.
            if (m == (num_mbis_ - 1) && b == 10) {
                *datalat_ = 1;
            }

            *datain_ = (cfg_packet >> b) & 1;
            *dataclk_ = 1;
            // See note above about data clock speed.
            wait_us(1);
            *dataclk_ = 0;
            wait_us(1);

            if (m == (num_mbis_ - 1) && b == 0) {
                *datalat_ = 0;
            }
        }
    }
}

void Display::configure_12bit() {
    bitmask_ = 0x0FFF;
    if (gridcfg_->panelcfg_->mbicfg_->model_ == MBI5030) {
        configure(0x22AC);
    } else {
        configure(0x3AAC);
    }
}

void Display::configure_16bit() {
    if (gridcfg_->panelcfg_->mbicfg_->model_ == MBI5030) {
        bitmask_ = 0xFFFF;
        configure(0x02AC);
    }
}

void Display::configure_default() {
    if (gridcfg_->panelcfg_->mbicfg_->model_ == MBI5030) {
        configure_16bit();
    } else {
        configure_12bit();
    }   
}

void Display::print_info() {
    printf("# mbis: %d\n", num_mbis_);
    printf("# pixels x: %d\n", pixelx_);
    printf("# pixels y: %d\n", pixely_);
}

///
// MBI LIBRARY <end>
///
}  // namespace mbipanel