From 3b3237c2ba1bb29f7d43fda9fdbc08bd0c32e5f9 Mon Sep 17 00:00:00 2001 From: root Date: Sat, 12 Oct 2013 12:13:58 +0100 Subject: first_full_makefile --- src/DM9000A.C | 239 +++++++++++++++++++++++++++++++++++++++++++++++ src/DM9000A.H | 72 +++++++++++++++ src/GPU.h | 31 +++++++ src/hello_led.c | 148 ++++++++++++++++++++++++++++++ src/pong3.c | 280 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 770 insertions(+) create mode 100644 src/DM9000A.C create mode 100644 src/DM9000A.H create mode 100644 src/GPU.h create mode 100644 src/hello_led.c create mode 100644 src/pong3.c (limited to 'src') diff --git a/src/DM9000A.C b/src/DM9000A.C new file mode 100644 index 0000000..7380729 --- /dev/null +++ b/src/DM9000A.C @@ -0,0 +1,239 @@ +#include +#include "DM9000A.H" + +#define msleep(msec) usleep(1000*msec); + + +#if 0 +//------------------------------------------------------------------------- +void iow(unsigned int reg, unsigned int data) +{ + IOWR(DM9000A_0_BASE,IO_addr,reg); + //usleep(STD_DELAY); + IOWR(DM9000A_0_BASE,IO_data,data); +} +//------------------------------------------------------------------------- +unsigned int ior(unsigned int reg) +{ + IOWR(DM9000A_0_BASE,IO_addr,reg); + //usleep(STD_DELAY); + return IORD(DM9000A_0_BASE,IO_data); +} +//------------------------------------------------------------------------- +void phy_write (unsigned int reg, unsigned int value) +{ + /* set PHY register address into EPAR REG. 0CH */ + iow(0x0C, reg | 0x40); /* PHY register address setting, and DM9000_PHY offset = 0x40 */ + + /* fill PHY WRITE data into EPDR REG. 0EH & REG. 0DH */ + iow(0x0E, ((value >> 8) & 0xFF)); /* PHY data high_byte */ + iow(0x0D, value & 0xFF); /* PHY data low_byte */ + + /* issue PHY + WRITE command = 0xa into EPCR REG. 0BH */ + iow(0x0B, 0x8); /* clear PHY command first */ + IOWR(DM9000A_0_BASE, IO_data, 0x0A); /* issue PHY + WRITE command */ + usleep(STD_DELAY); + IOWR(DM9000A_0_BASE, IO_data, 0x08); /* clear PHY command again */ + usleep(50); /* wait 1~30 us (>20 us) for PHY + WRITE completion */ +} +//------------------------------------------------------------------------- +/* DM9000_init I/O routine */ +unsigned int DM9000_init (void) /* initialize DM9000 LAN chip */ +{ + unsigned int i; + + /* set the internal PHY power-on (GPIOs normal settings) */ + iow(0x1E, 0x01); /* GPCR REG. 1EH = 1 selected GPIO0 "output" port for internal PHY */ + iow(0x1F, 0x00); /* GPR REG. 1FH GEPIO0 Bit [0] = 0 to activate internal PHY */ + msleep(5); /* wait > 2 ms for PHY power-up ready */ + + /* software-RESET NIC */ + iow(NCR, 0x03); /* NCR REG. 00 RST Bit [0] = 1 reset on, and LBK Bit [2:1] = 01b MAC loopback on */ + usleep(20); /* wait > 10us for a software-RESET ok */ + iow(NCR, 0x00); /* normalize */ + iow(NCR, 0x03); + usleep(20); + iow(NCR, 0x00); + + /* set GPIO0=1 then GPIO0=0 to turn off and on the internal PHY */ + iow(0x1F, 0x01); /* GPR PHYPD Bit [0] = 1 turn-off PHY */ + iow(0x1F, 0x00); /* PHYPD Bit [0] = 0 activate phyxcer */ + msleep(10); /* wait >4 ms for PHY power-up */ + + /* set PHY operation mode */ + phy_write(0,PHY_reset); /* reset PHY: registers back to the default states */ + usleep(50); /* wait >30 us for PHY software-RESET ok */ + phy_write(16, 0x404); /* turn off PHY reduce-power-down mode only */ + phy_write(4, PHY_txab); /* set PHY TX advertised ability: ALL + Flow_control */ + phy_write(0, 0x1200); /* PHY auto-NEGO re-start enable (RESTART_AUTO_NEGOTIATION + AUTO_NEGOTIATION_ENABLE) to auto sense and recovery PHY registers */ + //phy_write(0, 0x2000); + msleep(5); /* wait >2 ms for PHY auto-sense linking to partner */ + + /* store MAC address into NIC */ + for (i = 0; i < 6; i++) + iow(16 + i, ether_addr[i]); + + /* clear any pending interrupt */ + iow(ISR, 0x3F); /* clear the ISR status: PRS, PTS, ROS, ROOS 4 bits, by RW/C1 */ + iow(NSR, 0x2C); /* clear the TX status: TX1END, TX2END, WAKEUP 3 bits, by RW/C1 */ + + /* program operating registers~ */ + iow(NCR, NCR_set); /* NCR REG. 00 enable the chip functions (and disable this MAC loopback mode back to normal) */ + iow(0x08, BPTR_set); /* BPTR REG.08 (if necessary) RX Back Pressure Threshold in Half duplex moe only: High Water 3KB, 200 us */ + iow(0x09, FCTR_set); /* FCTR REG.09 (if necessary) Flow Control Threshold setting High/ Low Water Overflow 3KB/ 8KB */ + iow(0x0A, RTFCR_set); /* RTFCR REG.0AH (if necessary) RX/TX Flow Control Register enable TXPEN, BKPM (TX_Half), FLCE (RX) */ + iow(0x0F, 0x00); /* Clear the all Event */ + iow(0x2D, 0x80); /* Switch LED to mode 1 */ + iow(OTCR, OTCR_set); /* 100Mhz Internal clock */ + + //dong added + //iow(0x31, 0x01);//checksum generation enable + //iow(0x32, 0x02);//checksum checking enable, package will not be disscard even if CRC error + + /* set other registers depending on applications */ + iow(ETXCSR, ETXCSR_set); /* Early Transmit 12.5% */ + //iow(TCSCR, TCSCR_set); /* UDP and not IP Checksum activ. */ + + /* enable interrupts to activate DM9000 ~on */ + iow(IMR, INTR_set); /* IMR REG. FFH PAR=1 only, or + PTM=1& PRM=1 enable RxTx interrupts */ + + /* enable RX (Broadcast/ ALL_MULTICAST) ~go */ + iow(RCR , RCR_set | RX_ENABLE | PASS_MULTICAST); /* RCR REG. 05 RXEN Bit [0] = 1 to enable the RX machine/ filter */ + + /* RETURN "DEVICE_SUCCESS" back to upper layer */ + return (ior(0x2D)==0x80) ? DMFE_SUCCESS : DMFE_FAIL; +} +//------------------------------------------------------------------------- +/* Transmit one Packet TX I/O routine */ +unsigned int TransmitPacket(unsigned char *data_ptr,unsigned int tx_len) +{ + unsigned int i; + + /* mask NIC interrupts IMR: PAR only */ + iow(IMR, PAR_set); + + /* issue TX packet's length into TXPLH REG. FDH & TXPLL REG. FCH */ + iow(0xFD, (tx_len >> 8) & 0xFF); /* TXPLH High_byte length */ + iow(0xFC, tx_len & 0xFF); /* TXPLL Low_byte length */ + + /* wirte transmit data to chip SRAM */ + IOWR(DM9000A_0_BASE, IO_addr, MWCMD); /* set MWCMD REG. F8H TX I/O port ready */ + for (i = 0; i < tx_len; i += 2) + { + usleep(STD_DELAY); + IOWR(DM9000A_0_BASE, IO_data, (data_ptr[i+1]<<8)|data_ptr[i] ); + } + + usleep(100); + + /* issue TX polling command activated */ + iow(TCR , TCR_set | TX_REQUEST); /* TXCR Bit [0] TXREQ auto clear after TX completed */ + + /* wait TX transmit done */ + char tx_done = 0; + do + { + tx_done = ior(NSR)&0x0C; + } + while(!tx_done); + //usleep(STD_DELAY); + + /* clear the NSR Register */ + //iow(NSR,0x00); + + /* re-enable NIC interrupts */ + iow(IMR, INTR_set); + + /* RETURN "TX_SUCCESS" to upper layer */ + return DMFE_SUCCESS; +} +//------------------------------------------------------------------------- +/* Receive One Packet I/O routine */ +unsigned int ReceivePacket (unsigned char *data_ptr,unsigned int *rx_len) +{ + unsigned char rx_READY,GoodPacket; + unsigned int Tmp, RxStatus, i; + + RxStatus = rx_len[0] = 0; + GoodPacket=FALSE; + + iow(ISR, 0x01); + + /* mask NIC interrupts IMR: PAR only */ + iow(IMR, PAR_set); + + /* dummy read a byte from MRCMDX REG. F0H */ + rx_READY = ior(MRCMDX)&0x03; + + /* got most updated byte: rx_READY */ + rx_READY = IORD(DM9000A_0_BASE,IO_data)&0x03; + usleep(STD_DELAY); + + /* check if (rx_READY == 0x01): Received Packet READY? */ + if (rx_READY == DM9000_PKT_READY) + { + /* got RX_Status & RX_Length from RX SRAM */ + IOWR(DM9000A_0_BASE, IO_addr, MRCMD); /* set MRCMD REG. F2H RX I/O port ready */ + usleep(STD_DELAY); + RxStatus = IORD(DM9000A_0_BASE,IO_data); + usleep(STD_DELAY); + rx_len[0] = IORD(DM9000A_0_BASE,IO_data); + + /* Check this packet_status GOOD or BAD? */ + if ( !(RxStatus & 0xBF00) && (rx_len[0] < MAX_PACKET_SIZE) ) + { + /* read 1 received packet from RX SRAM into RX buffer */ + for (i = 0; i < rx_len[0]; i += 2) + { + usleep(STD_DELAY); + Tmp = IORD(DM9000A_0_BASE, IO_data); + data_ptr[i] = Tmp&0xFF; + data_ptr[i+1] = (Tmp>>8)&0xFF; + } + GoodPacket=TRUE; + } /* end if (GoodPacket) */ + else + { + printf("\nError\n"); + /* this packet is bad, dump it from RX SRAM */ + for (i = 0; i < rx_len[0]; i += 2) + { + usleep(STD_DELAY); + Tmp = IORD(DM9000A_0_BASE, IO_data); + } + rx_len[0] = 0; + } /* end if (!GoodPacket) */ + } /* end if (rx_READY == DM9000_PKT_READY) ok */ + else if(rx_READY) /* status check first byte: rx_READY Bit[1:0] must be "00"b or "01"b */ + { + printf(" RX failure!\n"); + /* software-RESET NIC */ + iow(NCR, 0x03); /* NCR REG. 00 RST Bit [0] = 1 reset on, and LBK Bit [2:1] = 01b MAC loopback on */ + usleep(20); /* wait > 10us for a software-RESET ok */ + iow(NCR, 0x00); /* normalize */ + iow(NCR, 0x03); + usleep(20); + iow(NCR, 0x00); + /* program operating registers~ */ + iow(NCR, NCR_set); /* NCR REG. 00 enable the chip functions (and disable this MAC loopback mode back to normal) */ + iow(0x08, BPTR_set); /* BPTR REG.08 (if necessary) RX Back Pressure Threshold in Half duplex moe only: High Water 3KB, 600 us */ + iow(0x09, FCTR_set); /* FCTR REG.09 (if necessary) Flow Control Threshold setting High/ Low Water Overflow 5KB/ 10KB */ + iow(0x0A, RTFCR_set); /* RTFCR REG.0AH (if necessary) RX/TX Flow Control Register enable TXPEN, BKPM (TX_Half), FLCE (RX) */ + iow(0x0F, 0x00); /* Clear the all Event */ + iow(0x2D, 0x80); /* Switch LED to mode 1 */ + iow(OTCR, OTCR_set); /* 100Mhz Internal clock */ + /* set other registers depending on applications */ + iow(ETXCSR, ETXCSR_set); /* Early Transmit 12.5% */ + /* enable interrupts to activate DM9000 ~on */ + iow(IMR, INTR_set); /* IMR REG. FFH PAR=1 only, or + PTM=1& PRM=1 enable RxTx interrupts */ + /* enable RX (Broadcast/ ALL_MULTICAST) ~go */ + iow(RCR , RCR_set | RX_ENABLE | PASS_MULTICAST); /* RCR REG. 05 RXEN Bit [0] = 1 to enable the RX machine/ filter */ + } /* end NIC H/W system Data-Bus error */ + + /* re-enable NIC interrupts */ + iow(IMR, INTR_set); + + return GoodPacket ? DMFE_SUCCESS : DMFE_FAIL; +} +//------------------------------------------------------------------------- +#endif diff --git a/src/DM9000A.H b/src/DM9000A.H new file mode 100644 index 0000000..47401f1 --- /dev/null +++ b/src/DM9000A.H @@ -0,0 +1,72 @@ +#ifndef __DM9000A_H__ +#define __DM9000A_H__ + +#define IO_addr 0 +#define IO_data 1 + +#define NCR 0x00 /* Network Control Register REG. 00 */ +#define NSR 0x01 /* Network Status Register REG. 01 */ +#define TCR 0x02 /* Transmit Control Register REG. 02 */ +#define RCR 0x05 /* Receive Control Register REG. 05 */ +#define ETXCSR 0x30 /* TX early Control Register REG. 30 */ +#define MRCMDX 0xF0 /* RX FIFO I/O port command READ for dummy read a byte from RX SRAM */ +#define MRCMD 0xF2 /* RX FIFO I/O port command READ from RX SRAM */ +#define MWCMD 0xF8 /* TX FIFO I/O port command WRITE into TX FIFO */ +#define ISR 0xFE /* NIC Interrupt Status Register REG. FEH */ +#define IMR 0xFF /* NIC Interrupt Mask Register REG. FFH */ +#define OTCR 0x2E /* NIC Operation Test Control Register REG. 2EH */ +#define TCSCR 0x31 /* Transmit Check Sum Control Register REG. 31H */ + +#define NCR_set 0x00 +#define TCR_set 0x00 +#define TX_REQUEST 0x01 /* TCR REG. 02 TXREQ Bit [0] = 1 polling Transmit Request command */ +#define TCR_long 0x40 /* packet disable TX Jabber Timer */ +#define RCR_set 0x30 /* skip CRC_packet and skip LONG_packet */ +#define RX_ENABLE 0x01 /* RCR REG. 05 RXEN Bit [0] = 1 to enable RX machine */ +#define RCR_long 0x40 /* packet disable RX Watchdog Timer */ +#define PASS_MULTICAST 0x08 /* RCR REG. 05 PASS_ALL_MULTICAST Bit [3] = 1: RCR_set value ORed 0x08 */ +#define BPTR_set 0x37 /* BPTR REG. 08 RX Back Pressure Threshold: High Water Overflow Threshold setting 3KB and Jam_Pattern_Time = 200 us */ +#define FCTR_set 0x38 /* FCTR REG. 09 High/ Low Water Overflow Threshold setting 3KB/ 8KB */ +#define RTFCR_set 0x29 /* RTFCR REG. 0AH RX/TX Flow Control Register enable TXPEN + BKPM(TX_Half) + FLCE(RX) */ +#define ETXCSR_set 0x80 /* Early Transmit Bit [7] Enable and Threshold 0~3: 12.5%, 25%, 50%, 75% */ +#define INTR_set 0x81 /* IMR REG. FFH: PAR +PRM, or 0x81: PAR + PRM + PTM */ +#define PAR_set 0x80 /* IMR REG. FFH: PAR only, RX/TX FIFO R/W Pointer Auto Return enable */ +#define OTCR_set 0x80 /* System Clock set = 100Mhz */ +#define TCSCR_set 0x00 /* UDP TCP IP auto send check */ + +#define PHY_reset 0x8000 /* PHY reset: some registers back to default value */ +#define PHY_txab 0x05e1 /* set PHY TX advertised ability: Full-capability + Flow-control (if necessary) */ +#define PHY_mode 0x3100 /* set PHY media mode: Auto negotiation (AUTO sense) */ + +#define STD_DELAY 20 /* standard delay 20 us */ + +#define DMFE_SUCCESS 0 +#define DMFE_FAIL 1 + +#define TRUE 1 +#define FALSE 0 + +#define DM9000_PKT_READY 0x01 /* packets ready to receive */ +#define PACKET_MIN_SIZE 0x40 /* Received packet min size */ +#define MAX_PACKET_SIZE 1522 /* RX largest legal size packet with fcs & QoS */ +#define DM9000_PKT_MAX 3072 /* TX 1 packet max size without 4-byte CRC */ +//------------------------------------------------------------------------- +unsigned char ether_addr[6]={ 0x01, 0x60, 0x6E, 0x11, 0x02, 0x0F }; +//------------------------------------------------------------------------- +void iow(unsigned int reg, unsigned int data); +unsigned int ior(unsigned int reg); +void phy_write(unsigned int reg, unsigned int value); +/* DM9000_init I/O routine */ +unsigned int DM9000_init (void); +/* Transmit One Packet TX I/O routine */ +unsigned int TransmitPacket(unsigned char *data_ptr,unsigned int tx_len); +/* Receive One Packet I/O routine */ +unsigned int ReceivePacket (unsigned char *data_ptr,unsigned int *rx_len); +//------------------------------------------------------------------------- + +#endif + + + + + diff --git a/src/GPU.h b/src/GPU.h new file mode 100644 index 0000000..fef1499 --- /dev/null +++ b/src/GPU.h @@ -0,0 +1,31 @@ +/* + * GPU.h + * + * Created on: Oct 11, 2013 + * Author: root + */ + +#ifndef GPU_H_ +#define GPU_H_ + +#define GPU_OFFSET 0x80 +#if 0 +#define GPU_WIDTH 640 +#define GPU_HEIGHT 480 +#else +#define GPU_WIDTH 800 +#define GPU_HEIGHT 600 +#endif + +#define GPU_REG_BLANK 0x0 +#define GPU_REG_SPRITE_X 0x1 +#define GPU_REG_SPRITE_Y 0x2 +#define GPU_REG_BAT0_Y 0x3 +#define GPU_REG_BAT1_Y 0x4 +#define GPU_REG_SPRITE_COLOUR 0x5 +#define GPU_REG_SPRITE_BASE 0x10 + +#define GPU_RGB(r,g,b) (((r) << 6) | ((g) << 3) | (b)) + + +#endif /* GPU_H_ */ diff --git a/src/hello_led.c b/src/hello_led.c new file mode 100644 index 0000000..9f472d7 --- /dev/null +++ b/src/hello_led.c @@ -0,0 +1,148 @@ +/* + * + * + * + * + */ +#include +#include +#include +#include +#include +#include "system.h" +#include "DM9000A.H" +#include "DM9000A.C" +//#include "sys/alt_irq.h" +#include <../src/alt_irq_register.c> + +#if 0 +unsigned int rx_len,i,packet_num,rx_cnt,tx_cnt; + + +#define data_lenght 1468 // Maximun Data lenght 1468 bytes +#define flenght (data_lenght+0x2E) //Total packet lenght + + unsigned char SND[flenght]; // Payload buffer + + unsigned char RX_DATA[flenght]; // Payload buffer + +//------------------------------------------------------------------------- +/* DM9000_init I/O routine */ + +//------------------------------------------------------------------------- +//------------------------------------------------------------------------- +//------------------------------------------------------------------------- + +void UDP_Init(void) + { + unsigned int IPsource_1,IPsource_2,IPsource_3,IPsource_4; + unsigned int IPdestination_1,IPdestination_2,IPdestination_3,IPdestination_4; + unsigned int IPchecksum1,IPchecksum2,IPchecksum3,IPchecksum4,IPchecksum5; + unsigned int Mac_source1, Mac_source2, Mac_source3, Mac_source4, Mac_source5, Mac_source6; + unsigned int Mac_dest1, Mac_dest2, Mac_dest3, Mac_dest4, Mac_dest5, Mac_dest6; + unsigned int lenght_h, lenght_l; + unsigned int IPlenght_h, IPlenght_l, IPlenght; + + IPsource_1 = 192; // Assign ie: 192.168.0.44 IP for the CD0 + IPsource_2 = 168; + IPsource_3 = 0; + IPsource_4 = 44; + + IPdestination_1 = 192; // Insert your IP data here + IPdestination_2 = 168; + IPdestination_3 = 0; + IPdestination_4 = 55; + + Mac_dest1 = 0xF4; // Insert your MAC address data here + Mac_dest2 = 0x6D; + Mac_dest3 = 0x04; + Mac_dest4 = 0x20; + Mac_dest5 = 0x9F; + Mac_dest6 = 0xF1; +// Mac_dest1 = 0XFF; // Insert your MAC address data here +// Mac_dest2 = 0xFF; +// Mac_dest3 = 0xFF; +// Mac_dest4 = 0xFF; +// Mac_dest5 = 0xFF; +// Mac_dest6 = 0xFF; + Mac_source1 = 0x01; // Assign an MAC address for DE2 + Mac_source2 = 0x60; + Mac_source3 = 0x6E; + Mac_source4 = 0x11; + Mac_source5 = 0x02; + Mac_source6 = 0x0F; + + lenght_h = ((data_lenght+8) & 0xFF00)>>8; // Convert in H byte and L byte + lenght_l = ((data_lenght+8) & 0x00FF); + + IPlenght = data_lenght + 8 + 20; // IP Lenght for IP header + IPlenght_h = (IPlenght & 0xFF00)>>8; // Convert in H byte and L byte + IPlenght_l = (IPlenght & 0x00FF); + // Calculating the IP checksum + IPchecksum1 = 0x0000C511 + (IPsource_1<<8)+IPsource_2+(IPsource_3<<8)+IPsource_4+ + (IPdestination_1<<8)+IPdestination_2+(IPdestination_3<<8)+(IPdestination_4)+ + (IPlenght_h<<8) + IPlenght_l; + IPchecksum2 = ((IPchecksum1&0x0000FFFF)+(IPchecksum1>>16)); + IPchecksum3 = 0x0000FFFF - IPchecksum2; + IPchecksum4 = (IPchecksum3 & 0xFF00)>>8; + IPchecksum5 = (IPchecksum3 & 0x00FF); + + unsigned char TXT[flenght] = { Mac_dest1, Mac_dest2, Mac_dest3, Mac_dest4 ,Mac_dest5, Mac_dest6, + Mac_source1, Mac_source2, Mac_source3, Mac_source4, Mac_source5, Mac_source6, + 0x08, 0x00, 0x45, 0x00, IPlenght_h, IPlenght_l, + 0x00, 0x00, 0x00, 0x00, 0x80, 0x11, + IPchecksum4, IPchecksum5, IPsource_1, IPsource_2, IPsource_3, IPsource_4, + IPdestination_1, IPdestination_2, IPdestination_3, IPdestination_4, 0x04, 0x00, + 0x04, 0x00, lenght_h, lenght_l, 0x00, 0x00}; + + for (i = 0; i < 42; i++) // Load the TXT[] in the SND (ethernet packet). + SND[i] = TXT[i]; + + for (i = 42; i < flenght-4; i++) // generating the data to send. + SND[i] = i-42; + + SND[i++] = 0x35; // This checksum is not correct... but also the net recieve the packets correctly. + SND[i++] = 0x15; // To do, calculate checksum. + SND[i++] = 0xF0; + SND[i++] = 0x13; + + + } + +void ethernet_interrupts(void) +{ + + ReceivePacket(RX_DATA,&rx_len); + rx_cnt++; + int j; + for(j=0;j +#include +#include +#include +#include +#include +#include "system.h" + +#include "GPU.h" + +#define msleep(msec) usleep(1000*msec); + + +static void +pio_write (unsigned int data) +{ + IOWR (PIO_0_BASE, 0, data); +} + + +static void +gpu_write (unsigned int reg, unsigned int data) +{ + IOWR (GPU_0_BASE, reg << 2, data); +} + + +static void +update_gpu (int x, int y, int bat0, int bat1) +{ + // set locations + gpu_write (GPU_REG_SPRITE_X, x + GPU_OFFSET); + gpu_write (GPU_REG_SPRITE_Y, y + GPU_OFFSET); + gpu_write (GPU_REG_BAT0_Y, bat0 + GPU_OFFSET); + gpu_write (GPU_REG_BAT1_Y, bat1 + GPU_OFFSET); + + + // enable video + gpu_write (GPU_REG_BLANK, 0); +} + + +static void +show_score (int score) +{ + // int to seven segment lookup: MSB dp g f e d c b a LSB + const uint8_t lookup[10] = + { 0x3F, 0x6, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x7, 0x7F, 0x6F }; + + uint8_t ss = 0; + + // show negative with DP + if (score < 0) + { + ss |= 0x80; + score = -score; + } + + if (score > 9) + score = 9; + + ss |= lookup[score]; + + pio_write (ss); +} + +static void +load_sprite (void) +{ + const uint16_t sprite[16] = + { 0x00C0, 0x03E0, 0x0FF8, 0x1FFE, 0x3FC7, 0x3F83, 0x3933, 0x3987, 0x3D37, + 0x3D37, 0x3D87, 0x3FFF, 0x1FFE, 0x07F8, 0x01E0, 0x00C0 + }; + const unsigned int n = sizeof (sprite) / sizeof (uint16_t); + unsigned int i; + + gpu_write (GPU_REG_SPRITE_COLOUR, GPU_RGB(7,2,0)); + + // squirt the bromium logo into the sprite + for (i = 0; i < n; ++i) + gpu_write (GPU_REG_SPRITE_BASE + i, sprite[i]); +} + + +static int +dir (int a, int b) +{ + if (a > b) + return 1; + if (a < b) + return -1; + return 0; +} + +static void +move_bat (int *b, int db) +{ + *b += dir (db, *b); +} + +static int +squish (int *v, int min, int max) +{ + if (*v < min) + { + *v = min; + return 1; + } + if (*v >= max) + { + *v = max - 1; + return 1; + } + return 0; +} + +static int +find_intersection (int x, int y, int xd, int yd, int t) +{ + + // super lazy - we should use the power of MATHS + + while (x != t) + { + x += xd; + y += yd; + + if (squish (&y, 0, GPU_HEIGHT)) + yd = -yd; + + if (squish (&x, 0, GPU_WIDTH)) + xd = -xd; + } + + return y; +} + +static int +has_missed (int y1, int y2) +{ + y1 = y1 - y2; + if (y1 < 0) + y1 = -y1; + if (y1 > 20) + return 1; + return 0; +} + +static int +x_speed (void) +{ + return (rand () % 10) + 1; +} + +static int +y_speed (void) +{ + return (rand () % 9) - 4; +} + + +int +main (void) +{ + int x, y, xd, yd; + int bat0, dbat0; + int bat1, dbat1; + int score = 0; + int serve = 0; + int i; + + printf ("Working...\n"); + + srand (12392184); + + bat0 = GPU_HEIGHT / 2; + bat1 = GPU_HEIGHT / 2; + + load_sprite (); + + for (;;) + { + xd = x_speed (); + yd = y_speed (); + + show_score (score); + + if (!serve) + { + x = 1; + y = bat0; + dbat0 = GPU_HEIGHT / 2; + dbat1 = find_intersection (x + xd, y + yd, xd, yd, GPU_WIDTH - 1); + } + else + { + x = GPU_WIDTH - 2; + y = bat1; + yd = -yd; + dbat0 = find_intersection (x + xd, y + yd, xd, yd, 0); + dbat1 = GPU_HEIGHT / 2; + } + serve = !serve; + + for (;;) + { + x += xd; + y += yd; + + + if (squish (&y, 0, GPU_HEIGHT)) + yd = -yd; + + if (squish (&x, 0, GPU_WIDTH)) + { + xd = x_speed (); + if (x) + xd = -xd; + yd = y_speed (); + + if (x) + { + + if (has_missed (y, bat1)) + { + score++; + break; + } + dbat0 = find_intersection (x + xd, y + yd, xd, yd, 0); + dbat1 = GPU_HEIGHT / 2; + + } + else + { + + if (has_missed (y, bat0)) + { + score--; + break; + } + dbat0 = GPU_HEIGHT / 2; + dbat1 = + find_intersection (x + xd, y + yd, xd, yd, GPU_WIDTH - 1); + + } + } + + move_bat (&bat0, dbat0); + move_bat (&bat1, dbat1); + + update_gpu (x, y, bat0, bat1); + + msleep (2); + } + + if (!serve) + { + dbat1 = GPU_HEIGHT / 2; + dbat0 = bat0; + } + else + { + dbat0 = GPU_HEIGHT / 2; + dbat1 = bat1; + } + + for (i = 0; i < 200; ++i) + { + if (i == 100) + show_score (score); + + move_bat (&bat0, dbat0); + move_bat (&bat1, dbat1); + + update_gpu (x, y, bat0, bat1); + msleep (2); + + } + } +} -- cgit v1.2.3