OpenCores
URL https://opencores.org/ocsvn/openarty/openarty/trunk

Subversion Repositories openarty

[/] [openarty/] [trunk/] [sw/] [board/] [oledtest.c] - Diff between revs 39 and 49

Go to most recent revision | Only display areas with differences | Details | Blame | View Log

Rev 39 Rev 49
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
//
//
// Filename:    oledtest.c
// Filename:    oledtest.c
//
//
// Project:     OpenArty, an entirely open SoC based upon the Arty platform
// Project:     OpenArty, an entirely open SoC based upon the Arty platform
//
//
// Purpose:     To see whether or not we can display an image onto the OLEDrgb
// Purpose:     To see whether or not we can display an image onto the OLEDrgb
//              PMod.  This program runs on the ZipCPU internal to the FPGA,
//              PMod.  This program runs on the ZipCPU internal to the FPGA,
//      and commands the OLEDrgb to power on, reset, initialize, and then to
//      and commands the OLEDrgb to power on, reset, initialize, and then to
//      display an alternating pair of images onto the display.
//      display an alternating pair of images onto the display.
//
//
//
//
// Creator:     Dan Gisselquist, Ph.D.
// Creator:     Dan Gisselquist, Ph.D.
//              Gisselquist Technology, LLC
//              Gisselquist Technology, LLC
//
//
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
//
//
// Copyright (C) 2015-2016, Gisselquist Technology, LLC
// Copyright (C) 2015-2016, Gisselquist Technology, LLC
//
//
// This program is free software (firmware): you can redistribute it and/or
// This program is free software (firmware): you can redistribute it and/or
// modify it under the terms of  the GNU General Public License as published
// modify it under the terms of  the GNU General Public License as published
// by the Free Software Foundation, either version 3 of the License, or (at
// by the Free Software Foundation, either version 3 of the License, or (at
// your option) any later version.
// your option) any later version.
//
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
// for more details.
// for more details.
//
//
// You should have received a copy of the GNU General Public License along
// You should have received a copy of the GNU General Public License along
// with this program.  (It's in the $(ROOT)/doc directory, run make with no
// with this program.  (It's in the $(ROOT)/doc directory, run make with no
// target there if the PDF file isn't present.)  If not, see
// target there if the PDF file isn't present.)  If not, see
// <http://www.gnu.org/licenses/> for a copy.
// <http://www.gnu.org/licenses/> for a copy.
//
//
// License:     GPL, v3, as defined and found on www.gnu.org,
// License:     GPL, v3, as defined and found on www.gnu.org,
//              http://www.gnu.org/licenses/gpl.html
//              http://www.gnu.org/licenses/gpl.html
//
//
//
//
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
//
//
//
//
 
#include "zipcpu.h"
#include "zipsys.h"
#include "zipsys.h"
#include "artyboard.h"
#include "artyboard.h"
 
 
void    idle_task(void) {
void    idle_task(void) {
        while(1)
        while(1)
                zip_idle();
                zip_idle();
}
}
 
 
extern int      splash[], mug[];
extern int      splash[], mug[];
 
 
#define OLED_PMODEN             0x0010001
 
#define OLED_PMODEN_OFF         0x0010000
 
#define OLED_IOPWR              OLED_PMODEN
 
#define OLED_VCCEN              0x0020002
 
#define OLED_VCC_DISABLE        0x0020000
 
#define OLED_RESET              0x0040000
 
#define OLED_RESET_CLR          0x0040004
 
#define OLED_FULLPOWER          (OLED_PMODEN|OLED_VCCEN|OLED_RESET_CLR)
 
#define OLED_POWER_DOWN         (OLED_PMODEN_OFF|OLED_VCC_DISABLE)
 
#define OLED_BUSY               1
 
#define OLED_DISPLAYON          0x0af
#define OLED_DISPLAYON          0x0af
 
 
 
 
#define MICROSECOND             (CLOCKFREQ_HZ/1000000)
#define MICROSECOND             (CLOCKFREQ_HZ/1000000)
 
 
#define OLED_DISPLAY_OFF
#define OLED_DISPLAY_OFF
 
 
 
 
 
 
/*
/*
 * timer_delay()
 * timer_delay()
 *
 *
 * Using the timer peripheral, delay by a given number of counts.  We'll sleep
 * Using the timer peripheral, delay by a given number of counts.  We'll sleep
 * during this delayed time, and wait on an interrupt to wake us.  As a result,
 * during this delayed time, and wait on an interrupt to wake us.  As a result,
 * this will only work from supervisor mode.
 * this will only work from supervisor mode.
 */
 */
void    timer_delay(int counts) {
void    timer_delay(int counts) {
        // Clear the PIC.  We want to exit from here on timer counts alone
        // Clear the PIC.  We want to exit from here on timer counts alone
        zip->pic = CLEARPIC;
        zip->z_pic = CLEARPIC;
 
 
        if (counts > 10) {
        if (counts > 10) {
                // Set our timer to count down the given number of counts
                // Set our timer to count down the given number of counts
                zip->tma = counts;
                zip->z_tma = counts;
                zip->pic = EINT(SYSINT_TMA);
                zip->z_pic = EINT(SYSINT_TMA);
                zip_rtu();
                zip_rtu();
                zip->pic = CLEARPIC;
                zip->z_pic = CLEARPIC;
        } // else anything less has likely already passed
        } // else anything less has likely already passed
}
}
 
 
void    wait_on_interrupt(int mask) {
void    wait_on_interrupt(int mask) {
        // Clear our interrupt only, but disable all others
        // Clear our interrupt only, but disable all others
        zip->pic = DALLPIC|mask;
        zip->z_pic = DALLPIC|mask;
        zip->pic = EINT(mask);
        zip->z_pic = EINT(mask);
        zip_rtu();
        zip_rtu();
        zip->pic = DINT(mask)|mask;
        zip->z_pic = DINT(mask)|mask;
}
}
 
 
void oled_clear(void);
void oled_clear(void);
 
 
/*
/*
 * The following outlines a series of commands to send to the OLEDrgb as part
 * The following outlines a series of commands to send to the OLEDrgb as part
 * of an initialization sequence.  The sequence itself was taken from the
 * of an initialization sequence.  The sequence itself was taken from the
 * MPIDE demo.  Single byte numbers in the sequence are just that: commands
 * MPIDE demo.  Single byte numbers in the sequence are just that: commands
 * to send 8-bit values across the port.  17-bit values with the 16th bit
 * to send 8-bit values across the port.  17-bit values with the 16th bit
 * set send two bytes (bits 15-0) to the port.  The OLEDrgb treats these as
 * set send two bytes (bits 15-0) to the port.  The OLEDrgb treats these as
 * commands (first byte) with an argument (the second byte).
 * commands (first byte) with an argument (the second byte).
 */
 */
const int       init_sequence[] = {
const int       init_sequence[] = {
        //  Unlock commands
        //  Unlock commands
        0x01fd12,
        0x01fd12,
        //  Display off
        //  Display off
        0x0ae,
        0x0ae,
        //  Set remap and data format
        //  Set remap and data format
        0x01a072,
        0x01a072,
        //  Set the start line
        //  Set the start line
        0x01a100,
        0x01a100,
        //  Set the display offset
        //  Set the display offset
        0x01a200,
        0x01a200,
        //  Normal display mode
        //  Normal display mode
        0x0000a4,
        0x0000a4,
        //  Set multiplex ratio
        //  Set multiplex ratio
        0x01a83f,
        0x01a83f,
        //  Set master configuration:
        //  Set master configuration:
        //      Use External VCC
        //      Use External VCC
        0x01ad8e,
        0x01ad8e,
        //  Disable power save mode
        //  Disable power save mode
        0x01b00b,
        0x01b00b,
        //  Set phase length
        //  Set phase length
        0x01b131,
        0x01b131,
        //  Set clock divide
        //  Set clock divide
        0x01b3f0,
        0x01b3f0,
        //  Set Second Pre-change Speed For ColorA
        //  Set Second Pre-change Speed For ColorA
        0x018a64,
        0x018a64,
        //  5l) Set Set Second Pre-charge Speed of Color B
        //  5l) Set Set Second Pre-charge Speed of Color B
        0x018b78,
        0x018b78,
        //  5m) Set Second Pre-charge Speed of Color C
        //  5m) Set Second Pre-charge Speed of Color C
        0x018c64,
        0x018c64,
        //  5n) Set Pre-Charge Voltage
        //  5n) Set Pre-Charge Voltage
        0x01bb3a,
        0x01bb3a,
        //  50) Set VCOMH Deselect Level
        //  50) Set VCOMH Deselect Level
        0x01be3e,
        0x01be3e,
        //  5p) Set Master Current
        //  5p) Set Master Current
        0x018706,
        0x018706,
        //  5q) Set Contrast for Color A
        //  5q) Set Contrast for Color A
        0x018191,
        0x018191,
        //  5r) Set Contrast for Color B
        //  5r) Set Contrast for Color B
        0x018250,
        0x018250,
        //  5s) Set Contrast for Color C
        //  5s) Set Contrast for Color C
        0x01837D,
        0x01837D,
        //  disable scrolling
        //  disable scrolling
        0x02e
        0x02e
};
};
 
 
/*
/*
 * oled_init()
 * oled_init()
 *
 *
 * This initializes and starts up the OLED.  While it sounds important, really
 * This initializes and starts up the OLED.  While it sounds important, really
 * the majority of the work necessary to do this is really captured in the
 * the majority of the work necessary to do this is really captured in the
 * init_sequence[] above.  This just primarily works to send that sequence to
 * init_sequence[] above.  This just primarily works to send that sequence to
 * the PMod.
 * the PMod.
 *
 *
 * We should be able to do all of this with the DMA: wait for an OLEDrgb not
 * We should be able to do all of this with the DMA: wait for an OLEDrgb not
 * busy interrupt, send one value, repeat until done.  For now ... we'll just
 * busy interrupt, send one value, repeat until done.  For now ... we'll just
 * leave that as an advanced exercise.
 * leave that as an advanced exercise.
 *
 *
 */
 */
void    oled_init(void) {
void    oled_init(void) {
        int     i;
        int     i;
 
 
        for(i=0; i<sizeof(init_sequence); i++) {
        for(i=0; i<sizeof(init_sequence); i++) {
                while(sys->io_oled.o_ctrl & OLED_BUSY)
                while(OLED_BUSY(sys->io_oled))
                        ;
                        ;
                sys->io_oled.o_ctrl = init_sequence[i];
                sys->io_oled.o_ctrl = init_sequence[i];
        }
        }
 
 
        oled_clear();
        oled_clear();
 
 
        // Wait 5ms
        // Wait 5ms
        timer_delay(CLOCKFREQ_HZ/200);
        timer_delay(CLOCKFREQ_HZ/200);
 
 
        // Turn on VCC and wait 100ms
        // Turn on VCC and wait 100ms
        sys->io_oled.o_data = OLED_VCCEN;
        sys->io_oled.o_data = OLED_VCCEN;
        // Wait 100 ms
        // Wait 100 ms
        timer_delay(CLOCKFREQ_HZ/10);
        timer_delay(CLOCKFREQ_HZ/10);
 
 
        // Send Display On command
        // Send Display On command
        sys->io_oled.o_ctrl = OLED_DISPLAYON;
        sys->io_oled.o_ctrl = OLED_DISPLAYON;
}
}
 
 
/*
/*
 * oled_clear()
 * oled_clear()
 *
 *
 * This should be fairly self-explanatory: it clears (sets to black) all of the
 * This should be fairly self-explanatory: it clears (sets to black) all of the
 * graphics memory on the OLED.
 * graphics memory on the OLED.
 *
 *
 * What may not be self-explanatory is that to send any more than three bytes
 * What may not be self-explanatory is that to send any more than three bytes
 * using our interface you need to send the first three bytes in o_ctrl,
 * using our interface you need to send the first three bytes in o_ctrl,
 * and set the next bytes (up to four) in o_a.  (Another four can be placed in
 * and set the next bytes (up to four) in o_a.  (Another four can be placed in
 * o_b.)  When the word is written to o_ctrl, the command goes over the wire
 * o_b.)  When the word is written to o_ctrl, the command goes over the wire
 * and o_a and o_b are reset.  Hence we set o_a first, then o_ctrl.  Further,
 * and o_a and o_b are reset.  Hence we set o_a first, then o_ctrl.  Further,
 * the '4' in the top nibble of o_ctrl indicates that we are sending 5-bytes
 * the '4' in the top nibble of o_ctrl indicates that we are sending 5-bytes
 * (4+5), so the OLEDrgb should see: 0x25,0x00,0x00,0x5f,0x3f.
 * (4+5), so the OLEDrgb should see: 0x25,0x00,0x00,0x5f,0x3f.
 */
 */
void    oled_clear(void) {
void    oled_clear(void) {
        while(sys->io_oled.o_ctrl & OLED_BUSY)
        while(OLED_BUSY(sys->io_oled))
                ;
                ;
        sys->io_oled.o_a = 0x5f3f0000;
        sys->io_oled.o_a = 0x5f3f0000;
        sys->io_oled.o_ctrl = 0x40250000;
        sys->io_oled.o_ctrl = 0x40250000;
        while(sys->io_oled.o_ctrl & OLED_BUSY)
        while(OLED_BUSY(sys->io_oled))
                ;
                ;
}
}
 
 
/*
/*
 * oled_fill
 * oled_fill
 *
 *
 * Similar to oled_clear, this fills a rectangle with a given pixel value.
 * Similar to oled_clear, this fills a rectangle with a given pixel value.
 */
 */
void    oled_fill(int c, int r, int w, int h, int pix) {
void    oled_fill(int c, int r, int w, int h, int pix) {
        int     ctrl; // We'll send this value out the control/command port
        int     ctrl; // We'll send this value out the control/command port
 
 
        if (c > 95) c = 95;
        if (c > 95) c = 95;
        if (c <  0) c =  0;
        if (c <  0) c =  0;
        if (r > 63) r = 63;
        if (r > 63) r = 63;
        if (r <  0) r =  0;
        if (r <  0) r =  0;
        if (w <  0) w = 0;
        if (w <  0) w = 0;
        if (h <  0) h = 0;
        if (h <  0) h = 0;
        if (c+w > 95) w = 95-c;
        if (c+w > 95) w = 95-c;
        if (r+h > 63) h = 63-r;
        if (r+h > 63) h = 63-r;
 
 
        // Enable the fill rectangle function, rather than just the outline
        // Enable the fill rectangle function, rather than just the outline
        while(sys->io_oled.o_ctrl & OLED_BUSY)
        while(OLED_BUSY(sys->io_oled))
                ;
                ;
        sys->io_oled.o_ctrl = 0x12601;
        sys->io_oled.o_ctrl = 0x12601;
 
 
        //
        //
        // Now, let's build the actual copy command
        // Now, let's build the actual copy command
        //
        //
        // This is an 11 byte command, consisting of the 0x22, followed by
        // This is an 11 byte command, consisting of the 0x22, followed by
        // the top left column and row of our rectangle, and then the bottom
        // the top left column and row of our rectangle, and then the bottom
        // right column and row.  That's the first five bytes.  The next six
        // right column and row.  That's the first five bytes.  The next six
        // bytes are the color of the border and the color of the fill.
        // bytes are the color of the border and the color of the fill.
        // Here, we set both colors to be identical.
        // Here, we set both colors to be identical.
        // 
        // 
        ctrl = 0xa0220000 | ((c&0x07f)<<8) | (r&0x03f);
        ctrl = 0xa0220000 | ((c&0x07f)<<8) | (r&0x03f);
        sys->io_oled.o_a = (((c+w)&0x07f)<<24) | (((r+h)&0x03f)<<16);
        sys->io_oled.o_a = (((c+w)&0x07f)<<24) | (((r+h)&0x03f)<<16);
        sys->io_oled.o_a|= ((pix >> 11) & 0x01f)<< 9;
        sys->io_oled.o_a|= ((pix >> 11) & 0x01f)<< 9;
        sys->io_oled.o_a|= ((pix >>  5) & 0x03f)    ;
        sys->io_oled.o_a|= ((pix >>  5) & 0x03f)    ;
        sys->io_oled.o_b = ((pix      ) & 0x01f)<<25;
        sys->io_oled.o_b = ((pix      ) & 0x01f)<<25;
        sys->io_oled.o_b|= ((pix >> 11) & 0x01f)<<17;
        sys->io_oled.o_b|= ((pix >> 11) & 0x01f)<<17;
        sys->io_oled.o_b|= ((pix >>  5) & 0x03f)<< 8;
        sys->io_oled.o_b|= ((pix >>  5) & 0x03f)<< 8;
        sys->io_oled.o_b|= ((pix      ) & 0x01f)<< 1;
        sys->io_oled.o_b|= ((pix      ) & 0x01f)<< 1;
 
 
        // Make certain we had finished with the port
        // Make certain we had finished with the port
        while(sys->io_oled.o_ctrl & OLED_BUSY)
        while(OLED_BUSY(sys->io_oled))
                ;
                ;
 
 
        // and send our new command.  Note that o_a and o_b were already set
        // and send our new command.  Note that o_a and o_b were already set
        // ahead of time, and are only now being sent together with this
        // ahead of time, and are only now being sent together with this
        // command.
        // command.
        sys->io_oled.o_ctrl = ctrl;
        sys->io_oled.o_ctrl = ctrl;
 
 
        // To be nice to whatever routine follows, we'll wait 'til the port
        // To be nice to whatever routine follows, we'll wait 'til the port
        // is clear again.
        // is clear again.
        while(sys->io_oled.o_ctrl & OLED_BUSY)
        while(OLED_BUSY(sys->io_oled))
                ;
                ;
}
}
 
 
/*
/*
 * oled_show_image(int *img)
 * oled_show_image(int *img)
 *
 *
 * This is a really simply function, for a really simple purpose: it copies
 * This is a really simply function, for a really simple purpose: it copies
 * a full size image to the device.  You'll notice two versions of the routine
 * a full size image to the device.  You'll notice two versions of the routine
 * below.  They are roughly identical in what they do.  The first version
 * below.  They are roughly identical in what they do.  The first version
 * sets up the DMA to transfer the data, one word at a time, from RAM to
 * sets up the DMA to transfer the data, one word at a time, from RAM to
 * the OLED.  One byte is transferred every at every OLED interrupt.  The other
 * the OLED.  One byte is transferred every at every OLED interrupt.  The other
 * version works roughly the same way, but first waits for the OLED port to be
 * version works roughly the same way, but first waits for the OLED port to be
 * clear before sending the image.  The biggest difference between the two
 * clear before sending the image.  The biggest difference between the two
 * approaches is that, when using the DMA, the routine finishes before the
 * approaches is that, when using the DMA, the routine finishes before the
 * DMA transfer is complete, whereas the second version of the routine
 * DMA transfer is complete, whereas the second version of the routine
 * returns as soon as the image transfer is complete.
 * returns as soon as the image transfer is complete.
 */
 */
void    oled_show_image(int *img) {
void    oled_show_image(int *img) {
#define USE_DMA
#define USE_DMA
#ifdef  USE_DMA
#ifdef  USE_DMA
                zip->dma.len= 6144;
                zip->z_dma.d_len= 6144;
                zip->dma.rd = img;
                zip->z_dma.d_rd = img;
                zip->dma.wr = (int *)&sys->io_oled.o_data;
                zip->z_dma.d_wr = (int *)&sys->io_oled.o_data;
                zip->dma.ctrl = DMAONEATATIME|DMA_CONSTDST|DMA_OLED;
                zip->z_dma.d_ctrl = DMAONEATATIME|DMA_CONSTDST|DMA_ONOLED;
#else
#else
                for(int i=0; i<6144; i++) {
                for(int i=0; i<6144; i++) {
                        while(sys->io_oled.o_ctrl & OLED_BUSY)
                        while(OLED_BUSY(sys->io_oled))
                                ;
                                ;
                        sys->io_oled.o_data = img[i];
                        sys->io_oled.o_data = img[i];
                }
                }
#endif
#endif
}
}
 
 
/*
/*
 * entry()
 * entry()
 *
 *
 * In all (current) ZipCPU programs, the programs start with an entry()
 * In all (current) ZipCPU programs, the programs start with an entry()
 * function that takes no arguments.  The actual bootup entry can be found
 * function that takes no arguments.  The actual bootup entry can be found
 * in the bootstrap.c file, but that calls us here.
 * in the bootstrap.c file, but that calls us here.
 *
 *
 */
 */
void    entry(void) {
void    main(int argc, char **argv) {
 
 
        // Since we'll be returning to userspace via zip_rtu() in order to
        // Since we'll be returning to userspace via zip_rtu() in order to
        // wait for an interrupt, let's at least place a valid program into
        // wait for an interrupt, let's at least place a valid program into
        // userspace to run: the idle_task.
        // userspace to run: the idle_task.
        unsigned        user_regs[16];
        unsigned        user_regs[16];
        for(int i=0; i<15; i++)
        for(int i=0; i<15; i++)
                user_regs[i] = 0;
                user_regs[i] = 0;
        user_regs[15] = (unsigned int)idle_task;
        user_regs[15] = (unsigned int)idle_task;
        zip_restore_context(user_regs);
        zip_restore_context(user_regs);
 
 
        // Clear the PIC.  We'll come back and use it later.  We clear it here
        // Clear the PIC.  We'll come back and use it later.  We clear it here
        // partly in order to avoid a race condition later.
        // partly in order to avoid a race condition later.
        zip->pic = CLEARPIC;
        zip->z_pic = CLEARPIC;
 
 
        // Wait till we've had power for at least a quarter second
        // Wait till we've had power for at least a quarter second
        if (0) {
        if (0) {
                // While this appears to do the task quite nicely, it leaves
                // While this appears to do the task quite nicely, it leaves
                // the master_ce line high within the CPU, and so it generates
                // the master_ce line high within the CPU, and so it generates
                // a whole lot of debug information in our Verilator simulation,
                // a whole lot of debug information in our Verilator simulation,
                // busmaster_tb.
                // busmaster_tb.
                int pwrcount = sys->io_pwrcount;
                int pwrcount = sys->io_pwrcount;
                do {
                do {
                        pwrcount = sys->io_pwrcount;
                        pwrcount = sys->io_pwrcount;
                } while((pwrcount>0)&&(pwrcount < CLOCKFREQ_HZ/4));
                } while((pwrcount>0)&&(pwrcount < CLOCKFREQ_HZ/4));
        } else {
        } else {
                // By using the timer and sleeping instead, the simulator can
                // By using the timer and sleeping instead, the simulator can
                // be made to run a *lot* faster, with a *lot* less debugging
                // be made to run a *lot* faster, with a *lot* less debugging
                // ... junk.
                // ... junk.
                int pwrcount = sys->io_pwrcount;
                int pwrcount = sys->io_pwrcount;
                if ((pwrcount > 0)&&(pwrcount < CLOCKFREQ_HZ/4)) {
                if ((pwrcount > 0)&&(pwrcount < CLOCKFREQ_HZ/4)) {
                        pwrcount = CLOCKFREQ_HZ/4 - pwrcount;
                        pwrcount = CLOCKFREQ_HZ/4 - pwrcount;
                        timer_delay(pwrcount);
                        timer_delay(pwrcount);
                }
                }
        }
        }
 
 
 
 
        // If the OLED is already powered, such as might be the case if
        // If the OLED is already powered, such as might be the case if
        // we rebooted but the board was still hot, shut it down
        // we rebooted but the board was still hot, shut it down
        if (sys->io_oled.o_data & 0x07) {
        if (sys->io_oled.o_data & 0x07) {
                sys->io_oled.o_data = OLED_VCC_DISABLE;
                sys->io_oled.o_data = OLED_VCC_DISABLE;
                // Wait 100 ms
                // Wait 100 ms
                timer_delay(CLOCKFREQ_HZ/10);
                timer_delay(CLOCKFREQ_HZ/10);
                // Shutdown the entire devices power
                // Shutdown the entire devices power
                sys->io_oled.o_data = OLED_POWER_DOWN;
                sys->io_oled.o_data = OLED_POWER_DOWN;
                // Wait 100 ms
                // Wait 100 ms
                timer_delay(CLOCKFREQ_HZ/10);
                timer_delay(CLOCKFREQ_HZ/10);
 
 
                // Now let's try to restart it
                // Now let's try to restart it
        }
        }
 
 
        // 1. Power up the OLED by applying power to VCC
        // 1. Power up the OLED by applying power to VCC
        //      This means we need to apply power to both the VCCEN line as well
        //      This means we need to apply power to both the VCCEN line as well
        //      as the PMODEN line.  We'll also set the reset line low, so the
        //      as the PMODEN line.  We'll also set the reset line low, so the
        //      device starts in a reset condition.
        //      device starts in a reset condition.
        sys->io_oled.o_data = OLED_PMODEN|OLED_RESET_CLR;
        sys->io_oled.o_data = OLED_PMODEN|OLED_RESET_CLR;
        timer_delay(4*MICROSECOND);
        timer_delay(4*MICROSECOND);
        sys->io_oled.o_data = OLED_RESET;
        sys->io_oled.o_data = OLED_RESET;
        timer_delay(4*MICROSECOND);
        timer_delay(4*MICROSECOND);
 
 
        // 2. Send the Display OFF command
        // 2. Send the Display OFF command
        //      This isn't necessary, since we already pulled RESET low.
        //      This isn't necessary, since we already pulled RESET low.
        //
        //
        // sys->io_oled.o_ctrl = OLED_DISPLAY_OFF;
        // sys->io_oled.o_ctrl = OLED_DISPLAY_OFF;
        //
        //
 
 
        // However, we must hold the reset line low for at least 3us, as per
        // However, we must hold the reset line low for at least 3us, as per
        // the spec.  We may also need to wait another 2us after that.  Let's
        // the spec.  We may also need to wait another 2us after that.  Let's
        // hold reset low for 4us here.
        // hold reset low for 4us here.
        timer_delay(4*MICROSECOND);
        timer_delay(4*MICROSECOND);
 
 
        // Clear the reset condition.
        // Clear the reset condition.
        sys->io_oled.o_data = OLED_RESET_CLR;
        sys->io_oled.o_data = OLED_RESET_CLR;
        // Wait another 4us.
        // Wait another 4us.
        timer_delay(4*MICROSECOND);
        timer_delay(4*MICROSECOND);
 
 
        // 3. Initialize the display to the default settings
        // 3. Initialize the display to the default settings
        //      This just took place during the reset cycle we just completed.
        //      This just took place during the reset cycle we just completed.
        //
        //
        oled_init();
        oled_init();
 
 
        // 4. Clear screen
        // 4. Clear screen
        // 5. Apply voltage
        // 5. Apply voltage
        // 6. Turn on display
        // 6. Turn on display
        // 7. Wait 100ms
        // 7. Wait 100ms
        //      We already stuffed this command sequence into the oled_init,
        //      We already stuffed this command sequence into the oled_init,
        //      so we're good here.
        //      so we're good here.
 
 
        while(1) {
        while(1) {
                sys->io_ledctrl = 0x0f0;
                sys->io_ledctrl = 0x0f0;
 
 
                sys->io_oled.o_ctrl = OLED_DISPLAYON;
                sys->io_oled.o_ctrl = OLED_DISPLAYON;
 
 
                oled_clear();
                oled_clear();
 
 
                // Let's start our writes at the top left of the GDDRAM
                // Let's start our writes at the top left of the GDDRAM
                // (screen memory)
                // (screen memory)
                while(sys->io_oled.o_ctrl & OLED_BUSY)
                while(OLED_BUSY(sys->io_oled))
                        ;
                        ;
                sys->io_oled.o_ctrl = 0x2015005f; // Sets column min/max address
                sys->io_oled.o_ctrl = 0x2015005f; // Sets column min/max address
 
 
                while(sys->io_oled.o_ctrl & OLED_BUSY)
                while(OLED_BUSY(sys->io_oled))
                        ;
                        ;
                sys->io_oled.o_ctrl = 0x2075003f; // Sets row min/max address
                sys->io_oled.o_ctrl = 0x2075003f; // Sets row min/max address
                while(sys->io_oled.o_ctrl & OLED_BUSY)
                while(OLED_BUSY(sys->io_oled))
                        ;
                        ;
 
 
                // Now ... finally ... we can send our image.
                // Now ... finally ... we can send our image.
                oled_show_image(splash);
                oled_show_image(splash);
                wait_on_interrupt(SYSINT_DMAC);
                wait_on_interrupt(SYSINT_DMAC);
 
 
                // Wait 25 seconds.  The LEDs are for a fun effect.
                // Wait 25 seconds.  The LEDs are for a fun effect.
                sys->io_ledctrl = 0x0f1;
                sys->io_ledctrl = 0x0f1;
                timer_delay(CLOCKFREQ_HZ*5);
                timer_delay(CLOCKFREQ_HZ*5);
                sys->io_ledctrl = 0x0f3;
                sys->io_ledctrl = 0x0f3;
                timer_delay(CLOCKFREQ_HZ*5);
                timer_delay(CLOCKFREQ_HZ*5);
                sys->io_ledctrl = 0x0f7;
                sys->io_ledctrl = 0x0f7;
                timer_delay(CLOCKFREQ_HZ*5);
                timer_delay(CLOCKFREQ_HZ*5);
                sys->io_ledctrl = 0x0ff;
                sys->io_ledctrl = 0x0ff;
                timer_delay(CLOCKFREQ_HZ*5);
                timer_delay(CLOCKFREQ_HZ*5);
                sys->io_ledctrl = 0x0fe;
                sys->io_ledctrl = 0x0fe;
                timer_delay(CLOCKFREQ_HZ*5);
                timer_delay(CLOCKFREQ_HZ*5);
 
 
 
 
                // Display a second image.
                // Display a second image.
                sys->io_ledctrl = 0x0fc;
                sys->io_ledctrl = 0x0fc;
                oled_show_image(mug);
                oled_show_image(mug);
                wait_on_interrupt(SYSINT_DMAC);
                wait_on_interrupt(SYSINT_DMAC);
 
 
                // Leave this one in effect for 5 seconds only.
                // Leave this one in effect for 5 seconds only.
                sys->io_ledctrl = 0x0f8;
                sys->io_ledctrl = 0x0f8;
                timer_delay(CLOCKFREQ_HZ*5);
                timer_delay(CLOCKFREQ_HZ*5);
        }
        }
 
 
        // We'll never get here, so this line is really just for form.
        // We'll never get here, so this line is really just for form.
        zip_halt();
        zip_halt();
}
}
 
 
 
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.