From 70506bee95fd2e6b7c07b11d2fa55fc0d3ddc5dc Mon Sep 17 00:00:00 2001 From: schneider Date: Mon, 22 Aug 2011 22:36:35 +0200 Subject: [PATCH] added geiger counter, pongo and scope l0dables --- firmware/l0dable/Geigerct.c | 167 ++++++++++++++++++ firmware/l0dable/pongo.c | 339 ++++++++++++++++++++++++++++++++++++ firmware/l0dable/scope.c | 125 +++++++++++++ 3 files changed, 631 insertions(+) create mode 100644 firmware/l0dable/Geigerct.c create mode 100644 firmware/l0dable/pongo.c create mode 100644 firmware/l0dable/scope.c diff --git a/firmware/l0dable/Geigerct.c b/firmware/l0dable/Geigerct.c new file mode 100644 index 0000000..d80a665 --- /dev/null +++ b/firmware/l0dable/Geigerct.c @@ -0,0 +1,167 @@ +/* + * geigerct.c + * + * + * Created on: 11.08.2011 + * Author: Turbo J + * + * Implements simple Geiger Counter + * Counts rising edges on P3_0 = BUSINT + * so you can directly connect the Geiger board + * from http://mightyohm.com/blog/products/geiger-counter/ + * + */ +#include +#include + +#include "basic/basic.h" +#include "basic/config.h" + +#include "lcd/render.h" +#include "lcd/print.h" + +#include "usetable.h" + +// Liberated from ARM Cortex M3 CMSIS core_cm3.h +// The processor definition headers for R0ket are incomplete :-/ + +#define __I +#define __IO volatile + +typedef struct { + __I uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPU ID Base Register */ + __IO uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control State Register */ + __IO uint32_t VTOR; /*!< Offset: 0x008 (R/W) Vector Table Offset Register */ + __IO uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt / Reset Control Register */ + __IO uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */ + __IO uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */ + __IO uint8_t SHP[12]; /*!< Offset: 0x018 (R/W) System Handlers Priority Registers (4-7, 8-11, 12-15) */ + __IO uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */ + __IO uint32_t CFSR; /*!< Offset: 0x028 (R/W) Configurable Fault Status Register */ + __IO uint32_t HFSR; /*!< Offset: 0x02C (R/W) Hard Fault Status Register */ + __IO uint32_t DFSR; /*!< Offset: 0x030 (R/W) Debug Fault Status Register */ + __IO uint32_t MMFAR; /*!< Offset: 0x034 (R/W) Mem Manage Address Register */ + __IO uint32_t BFAR; /*!< Offset: 0x038 (R/W) Bus Fault Address Register */ + __IO uint32_t AFSR; /*!< Offset: 0x03C (R/W) Auxiliary Fault Status Register */ + __I uint32_t PFR[2]; /*!< Offset: 0x040 (R/ ) Processor Feature Register */ + __I uint32_t DFR; /*!< Offset: 0x048 (R/ ) Debug Feature Register */ + __I uint32_t ADR; /*!< Offset: 0x04C (R/ ) Auxiliary Feature Register */ + __I uint32_t MMFR[4]; /*!< Offset: 0x050 (R/ ) Memory Model Feature Register */ + __I uint32_t ISAR[5]; /*!< Offset: 0x060 (R/ ) ISA Feature Register */ +} SCB_Type; + +#define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */ +#define SCB_BASE (SCS_BASE + 0x0D00UL) /*!< System Control Block Base Address */ +#define SCB ((SCB_Type *) SCB_BASE) /*!< SCB configuration struct */ + +uint32_t VectorTableInRAM[73] __attribute__ ((aligned(1024))); // VTOR needs 1024 Byte alignment, see UM10375.PDF + +void (*orig_handler_extint3)(void); // original EINT3 handler + +uint32_t volatile IntCtr; + +void ExtInt3_Handler(); + +// Remember: ram() must be the first function, place all other code AFTER +// because the Implementer seem not to know how to use section attributes + +static uint8_t mainloop(); + +void ram(void) { + uint8_t button; + uint32_t LEDs; + + // populate my Vector table + memcpy(VectorTableInRAM, 0, sizeof(VectorTableInRAM)); + orig_handler_extint3 = (void*) VectorTableInRAM[EINT3_IRQn + 16]; + VectorTableInRAM[EINT3_IRQn + 16] = (uint32_t) &ExtInt3_Handler; + // HACK: use RAM vector table to implement own External IRQ handler + SCB->VTOR = (uint32_t) &VectorTableInRAM[0]; + // TODO add DMB() here, as VTOR updates are NOT effective immediately + // + GPIO_GPIO3IEV |= 1; + GPIO_GPIO3IE |= 1; + GPIO_GPIO3DIR &= ~1; + GPIO_GPIO3IS &= ~1; + GPIO_GPIO0DATA &= ~1; + IOCON_PIO3_0 = (1 << 3) | (1 << 5); // Pull DOWN not Up, Hyst on + NVIC_EnableIRQ(EINT3_IRQn); + IntCtr = 0; + LEDs = 0; + mainloop(); + + GPIO_GPIO3IE &= ~1; // disable GPIO IRQ + NVIC_DisableIRQ(EINT3_IRQn); + // restore VTOR + SCB->VTOR = 0; + //TODO DMB(); Cortex Manual suggests DMB after setting VTOR + // not really needed in this case +} + +void ExtInt3_Handler() { + if (GPIO_GPIO3RIS & 0x01) { + GPIO_GPIO3IC |= (0x01); // ACK BUSINT + + + //GPIO_GPIO0DATA|=(1<<11); + IOCON_PIO1_11 = 0; + GPIO_GPIO1DATA |= (1 << 7); + GPIO_GPIO1DATA |= (1 << 11); + IntCtr++; + } else { + orig_handler_extint3(); + } +} + +static uint8_t mainloop() { + uint32_t ioconbak = IOCON_PIO1_11; + + uint32_t volatile oldCount=IntCtr; + uint32_t perMin=0; // counts in last 60 s + uint32_t startTime=_timectr; + uint8_t button; + IOCON_PIO1_11 = 0; + while (1) { + //GPIO_GPIO0DATA&=~(1<<11); + IOCON_PIO1_11 = ioconbak; + GPIO_GPIO1DATA &= ~(1 << 7); + GPIO_GPIO1DATA &= ~(1 << 11); + lcdClear(); + + lcdPrintln(" Geiger"); + lcdPrintln(" Counter"); + // #### + for (int i=0; i< (14*( _timectr-startTime))/(60*100);i++) { + lcdPrint("#"); + } + + lcdPrintln(""); + lcdPrintln("Counts:"); + lcdPrint(" "); + lcdPrintInt(IntCtr); + lcdPrintln(" total"); + lcdPrint(" "); + lcdPrintInt( perMin); + lcdPrintln("/min"); + // remember: We have a 10ms Timer counter + if ((startTime+60 *100 ) < _timectr) { + // dumb algo: Just use last 60 seconds count + perMin=IntCtr-oldCount; + startTime=_timectr; + oldCount=IntCtr; + } + lcdRefresh(); + delayms(42); + button = getInputRaw(); + + if (button != BTN_NONE) { + delayms(23);// debounce and wait till user release button + while (getInputRaw()!=BTN_NONE) delayms(23); + break; + } + } + IOCON_PIO1_11 = ioconbak; + return button; + +} + diff --git a/firmware/l0dable/pongo.c b/firmware/l0dable/pongo.c new file mode 100644 index 0000000..150ea22 --- /dev/null +++ b/firmware/l0dable/pongo.c @@ -0,0 +1,339 @@ +/**************************************************************************/ +/*! + @file pong.c + @author tverrbjelke & Simon + @date ccc2011 + @version 0.1 + + @section LICENSE + + Software License Agreement (BSD License) + + Copyright (c) 2010, microBuilder SARL + 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 +#include + +#include "basic/basic.h" +#include "basic/config.h" +#include "basic/random.h" + +#include "lcd/render.h" +#include "lcd/display.h" + +#include "usetable.h" + + +/******************************************** + ** Config Stuff +*********************************************/ + +/* Ball */ +#define PONG_BALL_SIZE ( 6 ) + + +/******************************************** +** Datatypes +*********************************************/ + + +typedef struct { + int8_t heigth; + int8_t width; + int8_t offset; // size between display border and paddle + int8_t pos; +} paddle_t; + + +typedef struct { + paddle_t paddle; + int8_t score; + bool second; +} player_t; + +typedef struct { + int8_t x; + int8_t y; + int8_t size; + int8_t angle; + int8_t speed_x; + int8_t speed_y; + bool moving; + int8_t player_has_ball; +} ball_t; + + + +ball_t ball1; +player_t player1; +player_t player2; + + +void print_score(); +void title_screen(); +void move_player(); +void draw_paddle(player_t ply); +void draw_ball(); +void check_border(); +void check_collision_player(player_t ply); +void move_bot(); +void end_game(); + +void init(); +/* void init_ball(ball_t ball); */ + +/******************************************** + ** Code Section +*********************************************/ + +void game(void) +{ + init(); + + while (1) + { + + lcdFill(0); + + if(gpioGetValue(RB_BTN0) == 0) + { + ram(); + return; + } + print_score(); + move_player(); + draw_ball(); + check_collision_player(player1); + check_collision_player(player2); + move_bot(); + draw_paddle(player2); + lcdDisplay(); + delayms(100); + } +} + +init() +{ + // init ball + ball1.size = PONG_BALL_SIZE; + ball1.x = 15; + ball1.y = 15; + ball1.speed_x = 5; + ball1.speed_y = 2; + ball1.moving = false; + ball1.player_has_ball = 1; + + // init player1 + player1.paddle.pos = 10; + player1.second = false; + player1.paddle.heigth = 20; + player1.paddle.width = 3; + player1.paddle.offset = 10; + player1.score = 0; + + // init player2 + player2.paddle.pos = 10; + player2.second = true; + player2.paddle.heigth = 20; + player2.paddle.width = 3; + player2.second = true; + player2.paddle.offset = RESX - player2.paddle.width - 10; + player2.score = 0; +} + +void print_score(void) +{ + DoInt(RESX/2-10, 10, player2.score); + DoInt(RESX/2+10, 10, player1.score); +} + +void move_player(void) +{ + if(gpioGetValue(RB_BTN3) == 0 && player1.paddle.pos > 0 ) + { + player1.paddle.pos-=3; + } + + if(gpioGetValue(RB_BTN2) == 0 && player1.paddle.pos < (RESY - player1.paddle.heigth)) + { + player1.paddle.pos+=3; + } + draw_paddle(player1); +} + + +void draw_paddle(player_t ply) +{ + for(int8_t i = 0; i < ply.paddle.heigth; i++) + { + for(int8_t j = 0; j < ply.paddle.width; j++) + { + lcdSetPixel(ply.paddle.offset - j, i+ply.paddle.pos, 1); + } + } +} + +void draw_ball(void) +{ + if(ball1.moving == true) + { + ball1.x += ball1.speed_x; + ball1.y += ball1.speed_y; + check_border(); + } + else + { + if(ball1.player_has_ball == 1) + { + ball1.y = player1.paddle.pos + player1.paddle.heigth/2 - ball1.size/2; + ball1.x = player1.paddle.offset + 3; + /* + if(ball1.speed_x < 0) + { + fprintf(stderr, "speed change"); + ball1.speed_x = -ball1.speed_x; + } + */ + + if(gpioGetValue(RB_BTN1) == 0) + { + ball1.moving = true; + } + } + else + { + ball1.y = player2.paddle.pos + player2.paddle.heigth/2 - ball1.size/2; + ball1.x = player2.paddle.offset - 3; + if(ball1.speed_x > 0) { + ball1.speed_x = -ball1.speed_x; + } + + ball1.moving = true; + } + + } + + for(int8_t i = 0; i < ball1.size; i++) + { + for(int8_t j = 0; j < ball1.size; j++) + { + lcdSetPixel(ball1.x + j, ball1.y + i, 1); + } + } +} + +void check_collision_player(player_t ply) { + + if (ply.second == true && ball1.moving == true) { + if(ball1.x >= (ply.paddle.offset - ply.paddle.width - 5) ) { + if(ball1.y > ply.paddle.pos && ball1.y < (ply.paddle.pos + ply.paddle.heigth) ) { + ball1.speed_x = - ball1.speed_x; + } + } + } + + if(ply.second == false && ball1.moving == true) { + if(ball1.x < (ply.paddle.offset + ply.paddle.width) ) { + if(ball1.y > ply.paddle.pos && ball1.y < (ply.paddle.pos + ply.paddle.heigth) ) { + ball1.speed_x = - ball1.speed_x; + } + } + } +} + +void check_border() { + if(ball1.speed_y < 0) { + if (ball1.y < 0) { + ball1.speed_y = - ball1.speed_y; + } + } else if (ball1.speed_y > 0) { + if(ball1.y > (RESY - ball1.size) ) { + ball1.speed_y = - ball1.speed_y; + } + } + + // ball is out + if(ball1.speed_x < 0) { + if(ball1.x < 0) { + ball1.speed_x = - ball1.speed_x; + player1.score++; + ball1.moving=false; + ball1.player_has_ball = 1; + } + } else { + if(ball1.x + ball1.size > RESX) { + ball1.speed_x = - ball1.speed_x; + player2.score++; + ball1.moving = false; + ball1.player_has_ball = 2; + } + } +} + + +void move_bot() { + int8_t pad_pos = player2.paddle.pos + (player2.paddle.heigth / 2); + int8_t real_y_ball = ball1.y + (ball1.size / 2); + int8_t m_speed = 4; + if(ball1.speed_x < 0) { +#ifdef SIMULATOR + fprintf(stderr,"Ball collide\n"); +#endif + if (pad_pos < (RESY/2) -3) { + player2.paddle.pos += m_speed; + } else if(pad_pos > (RESY/2) +1 ) { + player2.paddle.pos -= m_speed; + } + } else { + if ( pad_pos != real_y_ball ) { + if(pad_pos > real_y_ball) { + player2.paddle.pos -= m_speed; + } else if (pad_pos < real_y_ball) { + player2.paddle.pos += m_speed; + } + } + } +} + + +static const struct MENU mainmenu = {"PONG", { + {"Play Game", &game}, +// {"Multiplayer", &multi}, + {"Exit", &end_game}, + {NULL,NULL} +}}; + +void end_game(void) { + return; +} + +void ram(void) { + handleMenu(&mainmenu); +} diff --git a/firmware/l0dable/scope.c b/firmware/l0dable/scope.c new file mode 100644 index 0000000..b15fe48 --- /dev/null +++ b/firmware/l0dable/scope.c @@ -0,0 +1,125 @@ +/* + Simple oscilliscope with auto y-scale and variable x-scale. + Use joystick to select channel and x-scale and touch the hackbus ports + to generate some signals to see on your new oscilliscope. + Press the button to quit. + + Paul Gardner-Stephen paul@servalproject.org + + I hereby place this program into the public domain so far is as possible under law. + 13 August 2011. +*/ +#include +#include + +#include "basic/basic.h" +#include "basic/config.h" +#include "lcd/render.h" +#include "lcd/display.h" +#include "funk/mesh.h" +#include "usetable.h" +#include "core/adc/adc.c" + +void ram(void) { + int alive=0; + int ys[96]; + DoString(5,1,"Oscilliscope"); + lcdDisplay(); + + int i; + int ch=1; + int kok=1; + int xs=3,yscale=1; + char scale[]="01234567"; + + while (1) { + lcdSetPixel(alive,9,0); + alive++; alive&=63; + lcdSetPixel(alive,9,1); + + int ticks=64>>yscale; + for(i=10;i<60;i++) lcdSetPixel(7,i,0); + for(i=0;i>xs; + for(i=10;i<90;i++) lcdSetPixel(i,59,0); + for(i=0;i1)) { + // increase scale to fit data + yscale--; + } else if ((gnr>8)&&(yscale<64)) { + // reduce scale to fit data + yscale++; + } + gnr=0; lnr=0; + for(x=8;x<96;x++) { + int y; + y=adcRead(ch); + ysum+=y; + y=y-ybias; + y=y/yscale; + if (y<-25||y>25) gnr++; + else if (y<-12||y>12) lnr++; + y+=25; + if (y<0) y=0; + if (y>50) y=50; + if (y<0) y=0; if (y>31) y=31; + if (y!=ys[x]) { + lcdSetPixel(x,35+(ys[x]-25),0); + lcdSetPixel(x,35+(y-25),1); + ys[x]=y; + } + + // Crude means of delay with bits to deal with zealous optimisers + int delay=xs*xs; + for(i=0;i