Line 37... |
Line 37... |
//
|
//
|
//
|
//
|
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
//
|
//
|
//
|
//
|
|
#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
|
|
|
|
|
|
|
/*
|
/*
|
Line 76... |
Line 63... |
* 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);
|
|
|
/*
|
/*
|
Line 168... |
Line 155... |
*/
|
*/
|
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();
|
Line 202... |
Line 189... |
* 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
|
Line 228... |
Line 215... |
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
|
Line 251... |
Line 238... |
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)
|
Line 282... |
Line 269... |
* 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
|
}
|
}
|
Line 303... |
Line 290... |
* 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];
|
Line 316... |
Line 303... |
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
|
Line 400... |
Line 387... |
|
|
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);
|