Library(Beta) for Gameduino 2

Dependencies:   arduino

Dependents:   aa_gd_jw

GDTransport.h

Committer:
aluqard
Date:
2014-04-11
Revision:
0:9c211972beb2

File content as of revision 0:9c211972beb2:

#ifndef _GDTRANSPORT_H_
#define _GDTRANSPORT_H_

#include "mbed.h"
#include "arduino.h"

#ifndef DEBUGOUT
//#define DEBUGOUT (x,...)   std::printf(x, ##y);
#define DEBUGOUT(x, ...) std::printf(""x"\r\n", ##__VA_ARGS__);
#endif

// Convert degrees to Furmans
#define DEGREES(n) ((65536UL * (n)) / 360)

#define NEVER                0
#define LESS                 1
#define LEQUAL               2
#define GREATER              3
#define GEQUAL               4
#define EQUAL                5
#define NOTEQUAL             6
#define ALWAYS               7

#define ARGB1555             0
#define L1                   1
#define L4                   2
#define L8                   3
#define RGB332               4
#define ARGB2                5
#define ARGB4                6
#define RGB565               7
#define PALETTED             8
#define TEXT8X8              9
#define TEXTVGA              10
#define BARGRAPH             11

#define NEAREST              0
#define BILINEAR             1

#define BORDER               0
#define REPEAT               1

#define KEEP                 1
#define REPLACE              2
#define INCR                 3
#define DECR                 4
#define INVERT               5

#define DLSWAP_DONE          0
#define DLSWAP_LINE          1
#define DLSWAP_FRAME         2

#define INT_SWAP             1
#define INT_TOUCH            2
#define INT_TAG              4
#define INT_SOUND            8
#define INT_PLAYBACK         16
#define INT_CMDEMPTY         32
#define INT_CMDFLAG          64
#define INT_CONVCOMPLETE     128

#define TOUCHMODE_OFF        0
#define TOUCHMODE_ONESHOT    1
#define TOUCHMODE_FRAME      2
#define TOUCHMODE_CONTINUOUS 3

#define ZERO                 0
#define ONE                  1
#define SRC_ALPHA            2
#define DST_ALPHA            3
#define ONE_MINUS_SRC_ALPHA  4
#define ONE_MINUS_DST_ALPHA  5

#define BITMAPS              1
#define POINTS               2
#define LINES                3
#define LINE_STRIP           4
#define EDGE_STRIP_R         5
#define EDGE_STRIP_L         6
#define EDGE_STRIP_A         7
#define EDGE_STRIP_B         8
#define RECTS                9

#define OPT_MONO             1
#define OPT_NODL             2
#define OPT_FLAT             256
#define OPT_CENTERX          512
#define OPT_CENTERY          1024
#define OPT_CENTER           (OPT_CENTERX | OPT_CENTERY)
#define OPT_NOBACK           4096
#define OPT_NOTICKS          8192
#define OPT_NOHM             16384
#define OPT_NOPOINTER        16384
#define OPT_NOSECS           32768
#define OPT_NOHANDS          49152
#define OPT_RIGHTX           2048
#define OPT_SIGNED           256

#define LINEAR_SAMPLES       0
#define ULAW_SAMPLES         1
#define ADPCM_SAMPLES        2

// 'instrument' argument to GD.play()

#define SILENCE              0x00

#define SQUAREWAVE           0x01
#define SINEWAVE             0x02
#define SAWTOOTH             0x03
#define TRIANGLE             0x04

#define BEEPING              0x05
#define ALARM                0x06
#define WARBLE               0x07
#define CAROUSEL             0x08

#define PIPS(n)              (0x0f + (n))

#define HARP                 0x40
#define XYLOPHONE            0x41
#define TUBA                 0x42
#define GLOCKENSPIEL         0x43
#define ORGAN                0x44
#define TRUMPET              0x45
#define PIANO                0x46
#define CHIMES               0x47
#define MUSICBOX             0x48
#define BELL                 0x49

#define CLICK                0x50
#define SWITCH               0x51
#define COWBELL              0x52
#define NOTCH                0x53
#define HIHAT                0x54
#define KICKDRUM             0x55
#define POP                  0x56
#define CLACK                0x57
#define CHACK                0x58

#define MUTE                 0x60
#define UNMUTE               0x61

#define RAM_CMD              1081344UL
#define RAM_DL               1048576UL
#define RAM_PAL              1056768UL

#define REG_CLOCK            1057800UL
#define REG_CMD_DL           1058028UL
#define REG_CMD_READ         1058020UL
#define REG_CMD_WRITE        1058024UL
#define REG_CPURESET         1057820UL
#define REG_CSPREAD          1057892UL
#define REG_DITHER           1057884UL
#define REG_DLSWAP           1057872UL
#define REG_FRAMES           1057796UL
#define REG_FREQUENCY        1057804UL
#define REG_GPIO             1057936UL
#define REG_GPIO_DIR         1057932UL
#define REG_HCYCLE           1057832UL
#define REG_HOFFSET          1057836UL
#define REG_HSIZE            1057840UL
#define REG_HSYNC0           1057844UL
#define REG_HSYNC1           1057848UL
#define REG_ID               1057792UL
#define REG_INT_EN           1057948UL
#define REG_INT_FLAGS        1057944UL
#define REG_INT_MASK         1057952UL
#define REG_MACRO_0          1057992UL
#define REG_MACRO_1          1057996UL
#define REG_OUTBITS          1057880UL
#define REG_PCLK             1057900UL
#define REG_PCLK_POL         1057896UL
#define REG_PLAY             1057928UL
#define REG_PLAYBACK_FORMAT  1057972UL
#define REG_PLAYBACK_FREQ    1057968UL
#define REG_PLAYBACK_LENGTH  1057960UL
#define REG_PLAYBACK_LOOP    1057976UL
#define REG_PLAYBACK_PLAY    1057980UL
#define REG_PLAYBACK_READPTR 1057964UL
#define REG_PLAYBACK_START   1057956UL
#define REG_PWM_DUTY         1057988UL
#define REG_PWM_HZ           1057984UL
#define REG_ROTATE           1057876UL
#define REG_SOUND            1057924UL
#define REG_SWIZZLE          1057888UL
#define REG_TAG              1057912UL
#define REG_TAG_X            1057904UL
#define REG_TAG_Y            1057908UL
#define REG_TOUCH_ADC_MODE   1058036UL
#define REG_TOUCH_CHARGE     1058040UL
#define REG_TOUCH_DIRECT_XY  1058164UL
#define REG_TOUCH_DIRECT_Z1Z2 1058168UL
#define REG_TOUCH_MODE       1058032UL
#define REG_TOUCH_OVERSAMPLE 1058048UL
#define REG_TOUCH_RAW_XY     1058056UL
#define REG_TOUCH_RZ         1058060UL
#define REG_TOUCH_RZTHRESH   1058052UL
#define REG_TOUCH_SCREEN_XY  1058064UL
#define REG_TOUCH_SETTLE     1058044UL
#define REG_TOUCH_TAG        1058072UL
#define REG_TOUCH_TAG_XY     1058068UL
#define REG_TOUCH_TRANSFORM_A 1058076UL
#define REG_TOUCH_TRANSFORM_B 1058080UL
#define REG_TOUCH_TRANSFORM_C 1058084UL
#define REG_TOUCH_TRANSFORM_D 1058088UL
#define REG_TOUCH_TRANSFORM_E 1058092UL
#define REG_TOUCH_TRANSFORM_F 1058096UL
#define REG_TRACKER          1085440UL
#define REG_VCYCLE           1057852UL
#define REG_VOFFSET          1057856UL
#define REG_VOL_PB           1057916UL
#define REG_VOL_SOUND        1057920UL
#define REG_VSIZE            1057860UL
#define REG_VSYNC0           1057864UL
#define REG_VSYNC1           1057868UL

#define VERTEX2II(x, y, handle, cell) \
    ((2UL << 30) | (((x) & 511UL) << 21) | (((y) & 511UL) << 12) | (((handle) & 31) << 7) | (((cell) & 127) << 0))

#define ROM_PIXEL_FF        0xc0400UL

class GDTransport {
protected:
    SPI _spi;
    DigitalOut _cs;
    
    byte streaming;
    uint16_t wp;
    uint16_t freespace;

public:
    GDTransport(PinName mosi, PinName miso, PinName sclk, PinName cs)
        : _spi(mosi, miso, sclk)
        , _cs(cs)
    {
    }

    void begin() 
    {   
        _spi.format(8, 0);
        _spi.frequency(10000000);
     
        _cs = 1;   
        
        hostcmd(0x00); // FT_GPU_ACTIVE_M

        hostcmd(0x62); // Switch PLL output to 48MHz
            
        hostcmd(0x68); // FT_GPU_CORE_RESET
        
        _spi.frequency(16000000);
        
        byte chipid = rd(REG_ID);
    
        DEBUGOUT("0x%x", chipid);
        
        wp = 0;
        freespace = 4096 - 4;

        stream();
    }
    
    SPI* SPI()
    {
        return &_spi;
    }

    void cmd32(uint32_t x) 
    {
        if (freespace < 4) 
        {
            getfree(4);
        }
        wp += 4;
        freespace -= 4;
        union 
        {
            uint32_t c;
            uint8_t b[4];
        };
        c = x;
        _spi.write(b[0]);
        _spi.write(b[1]);
        _spi.write(b[2]);
        _spi.write(b[3]);
    }
    void cmdbyte(byte x) 
    {
        if (freespace == 0) 
        {
            getfree(1);
        }
        wp++;
        freespace--;
        _spi.write(x);
    }
    void cmd_n(byte *s, uint16_t n) 
    {
        if (freespace < n) 
        {
            getfree(n);
        }
        wp += n;
        freespace -= n;
        while (n > 8) 
        {
            n -= 8;
            _spi.write(*s++);
            _spi.write(*s++);
            _spi.write(*s++);
            _spi.write(*s++);
            _spi.write(*s++);
            _spi.write(*s++);
            _spi.write(*s++);
            _spi.write(*s++);
        }
        while (n--)
            _spi.write(*s++);
    }

    void flush() 
    {
        getfree(0);
    }
    uint16_t rp() 
    {
        uint16_t r = __rd16(REG_CMD_READ);
        
        if (r == 0xfff) 
        {
            for (;;) ;
        }
        return r;
    }
    void finish() 
    {
        wp &= 0xffc;
        __end();
        __wr16(REG_CMD_WRITE, wp);

        while (rp() != wp);
       
        stream();
    }

    byte rd(uint32_t addr)
    {
        __end(); // stop streaming
        __start(addr);
        byte r = _spi.write(0);
        stream();
        
        return r;
    }

    void wr(uint32_t addr, byte v)
    {
        __end(); // stop streaming
        __wstart(addr);
        _spi.write(v);
        stream();
    }

    uint16_t rd16(uint32_t addr)
    {
        uint16_t r = 0;
        __end(); // stop streaming
        __start(addr);
        r = _spi.write(0);
        r |= (_spi.write(0) << 8);
        stream();
        return r;
    }

    void wr16(uint32_t addr, uint32_t v)
    {
        __end(); // stop streaming
        __wstart(addr);
        
        _spi.write(v);
        _spi.write(v >> 8);
        stream();
    }

    uint32_t rd32(uint32_t addr)
    {
        __end(); // stop streaming
        __start(addr);
//        _spi.write(0);
        union {
            uint32_t c;
            uint8_t b[4];
        };
        b[0] = _spi.write(0);
        b[1] = _spi.write(0);
        b[2] = _spi.write(0);
        b[3] = _spi.write(0);
        stream();
        return c;
    }
    void rd_n(byte *dst, uint32_t addr, uint16_t n)
    {
        __end(); // stop streaming
        __start(addr);
//        _spi.write(0);
        while (n--)
            *dst++ = _spi.write(0);
        stream();
    }
    void wr_n(uint32_t addr, byte *src, uint16_t n)
    {
        __end(); // stop streaming
        __wstart(addr);
        while (n--)
            _spi.write(*src++);
        stream();
    }

    void wr32(uint32_t addr, unsigned long v)
    {
        __end(); // stop streaming
        __wstart(addr);
        _spi.write(v);
        _spi.write(v >> 8);
        _spi.write(v >> 16);
        _spi.write(v >> 24);
        stream();
    }

    uint32_t getwp(void) 
    {
        return RAM_CMD + (wp & 0xffc);
    }

    void bulk(uint32_t addr) 
    {
        __end(); // stop streaming
        __start(addr);
    }
    void resume(void) 
    {
        stream();
    }

    void __start(uint32_t addr) // start an SPI transaction to addr
    {
        _cs = 0;
        _spi.write(addr >> 16);
        _spi.write(addr >> 8);
        _spi.write(addr & 0xff );
        _spi.write(0);
    }

    void __wstart(uint32_t addr) // start an SPI write transaction to addr
    {
        _cs = 0;
        _spi.write(0x80 | (addr >> 16));
        _spi.write(addr >> 8);
        _spi.write(addr & 0xff);
    }

    void __end() // end the SPI transaction
    {
        _cs = 1;
    }

    void stop() // end the SPI transaction
    {
        wp &= 0xffc;
        __end();
        __wr16(REG_CMD_WRITE, wp);
    }

    void stream(void) {
        __end();
        __wstart(RAM_CMD + (wp & 0xfff));
    }

    uint32_t __rd16(uint32_t addr)
    {
        uint32_t r;
        
        __start(addr);
        r = _spi.write(0);
        r |= (_spi.write(0) << 8);
        __end();
        return r;
    }

    void __wr16(uint32_t addr, uint32_t v)
    {
        __wstart(addr);
        _spi.write(lowByte(v));
        _spi.write(highByte(v));
        __end();
    }

    void hostcmd(byte a)
    {
        _cs = 0;

        _spi.write(a);
        _spi.write(0x00);
        _spi.write(0x00);
        
        _cs = 1;
        
        delay(60);
    }

    void getfree(uint16_t n)
    {
        wp &= 0xfff;
        __end();
        __wr16(REG_CMD_WRITE, wp & 0xffc);
        do {
            uint16_t fullness = (wp - rp()) & 4095;
            freespace = (4096 - 4) - fullness;
        } while (freespace < n);
        stream();
    }
};

#endif