/**************************************************************************/
/*!
@file main.c
@section LICENSE
Software License Agreement (BSD License)
Copyright (c) 2013, K. Townsend (microBuilder.eu)
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holders nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**************************************************************************/
#include <stdio.h>
#include "LPC8xx.h"
#include "gpio.h"
#include "mrt.h"
#include "uart.h"
#include "spi.h"
#if defined(__CODE_RED)
#include <cr_section_macros.h>
#include <NXP/crp.h>
__CRP const unsigned int CRP_WORD = CRP_NO_CRP ;
#endif
// hmm, this seems to assert the bit number of the LED
// #define LED_LOCATION (2)
// let's try that for my sync pin..
#define SYNC_LOCATION (2)
// as it says: the line counter
volatile int line_counter;
// define PAL signals
#define VTOTAL 312
#define VSYNCSTART VTOTAL-8
#define VSYNCEND VTOTAL-4
#define VISIBLESTART30
#define VISIBLEEND270
#define HSYNCWIDTH12-1
// #define HSYNCWIDTH16-1
#define MAX_X26
#define MAX_YVISIBLEEND-8
// define BAT positions and size
#define BATLX 3
#define BATRX MAX_X-BATLX-1
#define BATSIZE 20
#define SCORELX((MAX_X/2)-3)
#define SCORERX((MAX_X/2)+3)
#define SCOREY(VISIBLESTART+10)
#define BATSTEP((VISIBLEEND-VISIBLESTART)/32)
#define COMP_VP0
#define COMP_VM1
#define COMPSA(0x1 << 6)
#define EDGECLR(0x1 << 20)
#define COMPSTAT(0x1 << 21)
#define COMPEDGE(0x1 << 23)
void SwitchMatrix_Init()
{
/* Enable SWM clock */
LPC_SYSCON->SYSAHBCLKCTRL |= (1<<7);
// Enable IOCON clock
LPC_SYSCON->SYSAHBCLKCTRL |= (1<<18);
/* Enable AHB clock to the Comparator. */
LPC_SYSCON->SYSAHBCLKCTRL |= (1 << 19);
/* fixed Pin Assign 1 bit Configuration */
/* ACMP_I1 */
/* ACMP_I2 */
/* RESET */
LPC_SWM->PINENABLE0 = 0xffffffbdUL;
/* Pin Assign 8 bit Configuration */
/* SPI0_MOSI */
LPC_SWM->PINASSIGN4 = 0xffffff03UL;
/* Set the SYNC output pin to output (1 = output, 0 = input) */
LPC_GPIO_PORT->DIR0 |= (1 << SYNC_LOCATION);
// init SPI to run at 30/6 = 5 MHz, no delay (0)
spiInit(LPC_SPI0,(6-1),0);
/* Comparator should be powered up first. Use of comparator requires BOD ? */
LPC_SYSCON->PDRUNCFG &= ~( (0x1 << 15) | (0x1 << 3) );
/* Peripheral reset control to Comparator, a "1" bring it out of reset. */
LPC_SYSCON->PRESETCTRL &= ~(1 << 12);
LPC_SYSCON->PRESETCTRL |= (1 << 12);
/* Pin I/O Configuration */
// disable pull up resistors on analog input pins
LPC_IOCON->PIO0_0 &= ~(0x3 << 3);
LPC_IOCON->PIO0_1 &= ~(0x3 << 3);
// preset analog comparator CTL register
// select COMP_VP_SEL for voltage ladder output
// select COMP_VM_SEL for ACMP_I2
// deselect COMPSA
LPC_CMP->CTRL |= ((2<<11));
// disable IOCON clock
LPC_SYSCON->SYSAHBCLKCTRL &= ~(1<<18);
/* SWM clock no longer needed now it's configured */
LPC_SYSCON->SYSAHBCLKCTRL &= ~(1<<7);
}
static unsigned char bitmap[][8]={
{255,129,129,129,129,129,129,255},// 0
{1,1,1,1,1,1,1,1},// 1
{255,1,1,255,128,128,128,255},// 2
{255,1,1,15,1,1,1,255},// 3
{129,129,129,255,1,1,1,1},// 4
{255,128,128,255,1,1,1,255},// 5
{255,128,128,255,129,129,129,255},// 6
{255,1,1,1,1,1,1,1},// 7
{255,129,129,255,129,129,129,255},// 8
{255,129,129,255,1,1,1,255},// 9
{24,60,126,126,126,126,60,24},// ball
};
volatile unsigned char linebuffer[MAX_X+1];
volatile unsigned short ball_x,ball_y;
volatile unsigned short batly,batry;
volatile unsigned short score_l,score_r;
volatile unsigned char vbl_flag;
volatile unsigned shortpaddle_l,paddle_r;
volatile unsigned int paddle_counter;
int main(void)
{
signed char dx,dy,by;
SystemCoreClockUpdate();// retrieve the clock
/* Initialise the GPIO block */
gpioInit();
/* Configure the switch matrix (setup pins) */
SwitchMatrix_Init();
/* Configure the multi-rate timer for 64us ticks and start interrupts */
mrtInit(__SYSTEM_CLOCK/15525);
// ball
ball_x=100;
ball_y=50;
score_l=0;
score_r=0;
batly=100;
batry=100;
// set vector
dx=2;
dy=1;
by=1;
// endless loop
while(1)
{
vbl_flag=0;
//LPC_CMP->LAD=1;
while (!vbl_flag);// wait for vsync to happen
//LPC_CMP->LAD=1|(15<<1);
// bounce ball around
ball_x+=dx;
if (ball_x > ((MAX_X-1)*8))
{
if (dx>0)
{
if (score_l<9) score_l++; else score_l=0;
}
else
{
if (score_r<9) score_r++; else score_r=0;
}
dx=-dx;
ball_x+=dx;
}
if (( LPC_CMP->CTRL & (1<<21)) !=0 ) score_r=1; else score_r=0;
ball_y+=dy;
if ((ball_y>(MAX_Y-1)) || (ball_y<VISIBLESTART))
{
dy=-dy;
}
// bounce left bat
batly+=by;
if ((batly>(VISIBLEEND-BATSIZE-1)) || (batly<VISIBLESTART))
{
by=-by;
}
//batry=VISIBLESTART+(paddle_counter*BATSTEP);
//paddle_counter++;
//paddle_counter &= 0x1fUL;
//LPC_CMP->LAD=(1 | (paddle_counter<<1));
}
}
// state machine list for the complete screen output
static void state_before_vsync(void);
static void hsync()
{
// set sync pin low
LPC_GPIO_PORT->CLR0 = 1 << SYNC_LOCATION;
// send three more nulls (sync width)
while ( (LPC_SPI0->STAT & SPI_STAT_TXRDY) == 0 );
LPC_SPI0->TXDATCTL = SPI_TXDATCTL_FSIZE(HSYNCWIDTH)| SPI_TXDATACTL_RXIGNORE ;
while ( (LPC_SPI0->STAT & SPI_STAT_TXRDY) == 0 );
LPC_SPI0->TXDATCTL = SPI_TXDATCTL_FSIZE(HSYNCWIDTH)| SPI_TXDATACTL_RXIGNORE ;
while ( (LPC_SPI0->STAT & SPI_STAT_TXRDY) == 0 );
LPC_SPI0->TXDATCTL = SPI_TXDATCTL_FSIZE(HSYNCWIDTH)| SPI_TXDATACTL_RXIGNORE ;
// set sync pin high
LPC_GPIO_PORT->SET0 = 1 << SYNC_LOCATION;
}
static void (*state)(void) = state_before_vsync;
// emit a line from the visible area (framebuffer)
static void state_visible_area(void) {
register unsigned short ofs_y;
register unsigned short ofs_x;
register unsigned short temp16;
extern volatile unsigned char linebuffer[];
// always emit horizontal sync
hsync();
// wait for active part to start
if (line_counter < VISIBLESTART) return;
// if less than active part end
if( line_counter<VISIBLEEND+1)
{
// emit back porch (black level)
while ( (LPC_SPI0->STAT & SPI_STAT_TXRDY) == 0 );
LPC_SPI0->TXDATCTL = SPI_TXDATCTL_FSIZE(16-1) | SPI_TXDATACTL_RXIGNORE;
while ( (LPC_SPI0->STAT & SPI_STAT_TXRDY) == 0 );
LPC_SPI0->TXDATCTL = SPI_TXDATCTL_FSIZE(8-1) | SPI_TXDATACTL_RXIGNORE;
//while ( (LPC_SPI0->STAT & SPI_STAT_TXRDY) == 0 );
//LPC_SPI0->TXDATCTL = SPI_TXDATCTL_FSIZE(16-1) | SPI_TXDATACTL_RXIGNORE;
// enable ladder and set voltage ladder
paddle_counter++;
paddle_counter &= 0x1f;
LPC_CMP->LAD = (1|(paddle_counter<<1));
// active line part
// now send MAX_X * 8 dots
int n;
// send contents of linebuffer
for(n=0; n<MAX_X; n++){
while ( (LPC_SPI0->STAT & SPI_STAT_TXRDY) == 0 );
LPC_SPI0->TXDATCTL = SPI_TXDATCTL_FSIZE(8-1) | linebuffer[n] | SPI_TXDATACTL_RXIGNORE;
linebuffer[n]=0;// clear linebuffer along the way
}
// now send 1 bytes blanking
while ( (LPC_SPI0->STAT & SPI_STAT_TXRDY) == 0 );
LPC_SPI0->TXDATCTL = SPI_TXDATCTL_FSIZE(8-1)| SPI_TXDATACTL_RXIGNORE ;
// check Analog comparator output bit and set batry if set (first time)
if ((LPC_CMP->CTRL & (1UL<<21)) && (batry==VISIBLESTART)) batry+=(paddle_counter*BATSTEP);
// mount bats left and right and score
ofs_y=line_counter-batly;
if (ofs_y<BATSIZE) linebuffer[BATLX]|=0x0f;
ofs_y=line_counter-batry;
if (ofs_y<BATSIZE) linebuffer[BATRX]|=0xf0;
ofs_y=line_counter-SCOREY;
if (ofs_y<8)
{
linebuffer[SCORELX]|=bitmap[score_l][ofs_y];
linebuffer[SCORERX]|=bitmap[score_r][ofs_y];
}
// place the ball
ofs_y=line_counter-ball_y;
if (ofs_y<8)
{
ofs_x=ball_x>>3;
// pre shift object data
temp16=bitmap[10][ofs_y]<<(8-(ball_x % 8));
// place object data in linebuffer
linebuffer[ofs_x]|=(temp16>>8);
linebuffer[ofs_x+1]|=(temp16 & 0xff);
}
}
else state = state_before_vsync;
}
static void state_after_vsync(void)
{ // VSYNC is over, now wait for end of frame
// always emit horizontal sync
hsync();
if (line_counter != VTOTAL) return;
line_counter = 0; // reset line counter
batry=VISIBLESTART;
vbl_flag=1;
state = state_visible_area; // we're in visible mode
}
static void state_during_vsync(void)
{ // VSYNC is active
// keep sending horizontal sync pulses (inverted)
LPC_GPIO_PORT->SET0 = 1 << SYNC_LOCATION;
// send three more nulls (sync width)
while ( (LPC_SPI0->STAT & SPI_STAT_TXRDY) == 0 );
LPC_SPI0->TXDATCTL = SPI_TXDATCTL_FSIZE(HSYNCWIDTH)| SPI_TXDATACTL_RXIGNORE ;
while ( (LPC_SPI0->STAT & SPI_STAT_TXRDY) == 0 );
LPC_SPI0->TXDATCTL = SPI_TXDATCTL_FSIZE(HSYNCWIDTH)| SPI_TXDATACTL_RXIGNORE ;
while ( (LPC_SPI0->STAT & SPI_STAT_TXRDY) == 0 );
LPC_SPI0->TXDATCTL = SPI_TXDATCTL_FSIZE(HSYNCWIDTH)| SPI_TXDATACTL_RXIGNORE ;
// set sync pin low
LPC_GPIO_PORT->CLR0 = 1 << SYNC_LOCATION;
if (line_counter != VSYNCEND) return;
LPC_GPIO_PORT->SET0 = 1 << SYNC_LOCATION;
state = state_after_vsync; // VSYNC is done
}
static void state_before_vsync(void)
{
// always emit horizontal sync
hsync();
// wait for VSYNC start
if (line_counter != VSYNCSTART)return;
state = state_during_vsync; // VSYNC has started
}
void MRT_IRQHandler(void)
{
if ( LPC_MRT->Channel[0].STAT & MRT_STAT_IRQ_FLAG )
{
state();
line_counter++;
LPC_MRT->Channel[0].STAT = MRT_STAT_IRQ_FLAG; /* clear interrupt flag */
}
return;
}
|