BBC Microbit + Random 1

Photo

BBC Microbit + Random 1

Sketch

// One random dot
// Copyright (C) 2019 https://www.roboticboat.uk
// 4639f922-1502-4cc9-bf6e-953d77e57d9e
//
// This program is free software: you can redistribute it and/or 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 your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
// These Terms shall be governed and construed in accordance with the laws of
// England and Wales, without regard to its conflict of law provisions.
// Using the Arduino IDE select
// File->Preferences
// Additional Boards Managers URLs add. Separate with comma if other links exist
// https://sandeepmistry.github.io/arduino nRF5/package_nRF5_boards_index.json
// Tools->Boards Manager, search for nRF5
// I installed Nordic Semiconductor nRF5 Boards by Sandeep Mistry
// Tools->Board, select BBC micro:bit
// Tools->Softdevice, select S110
#define SCREEN_WIDTH 5
#define SCREEN_HEIGHT 5
#define FONT_WIDTH 5
#define FONT_HEIGHT 5
volatile uint8_t nextGroup = 0;
// Allocate memory to store the screen pixels
bool** screen = new bool*[SCREEN_HEIGHT];
int x = 2;
int y = 2;
int random_number;
void setup() {
// These pins relate to the 5x5 display LEDs
pinMode(3, OUTPUT);
pinMode(4, OUTPUT);
pinMode(6, OUTPUT);
pinMode(7, OUTPUT);
pinMode(9, OUTPUT);
pinMode(10, OUTPUT);
pinMode(23, OUTPUT);
pinMode(24, OUTPUT);
pinMode(25, OUTPUT);
// Allocate memory
for (int i=0; i<SCREEN_HEIGHT; i++){
screen[i] = new bool[SCREEN_WIDTH];
}
// Initialise array
for (int i=0; i<SCREEN_HEIGHT; i++)
{
for (int j=0; j<SCREEN_WIDTH; j++)
{
screen[i][j] = false;
}
}
screen[x][y] = true;
// Update the User
Serial.begin(9600);
configTimer2();
}
void loop() {
// Sample the next random number
random_number = rand() % 8 + 1;
screen[x][y] = false;
switch (random_number){
case 1 :
x = x +1;
if (x > 4) x = 4;
break;
case 2 :
x = x - 1;
if (x < 0) x = 0;
break;
case 3 :
y = y + 1;
if (y > 4) y = 4;
break;
case 4 :
y = y - 1;
if (y < 0) y = 0;
break;
case 5 :
x = x + 1;
if (x > 4) x = 4;
y = y + 1;
if (y > 4) y = 4;
break;
case 6 :
x = x + 1;
if (x > 4) x = 4;
y = y - 1;
if (y < 0) y = 0;
break;
case 7 :
x = x - 1;
if (x < 0) x = 0;
y = y - 1;
if (y < 0) y = 0;
break;
case 8 :
x = x - 1;
if (x < 0) x = 0;
y = y + 1;
if (y > 4) y = 4;
break;
}
screen[x][y] = true;
delay(100);
}
// extern "C" is a linkage-specification, calling a c interface from a C++ program
// We don't want the C++ compiler giving the function a different name
extern "C" { void TIMER2_IRQHandler(void) {
// Check is the interrupt has been called
if (NRF_TIMER2->EVENTS_COMPARE[0] == 0 || (NRF_TIMER2->INTENSET & TIMER_INTENSET_COMPARE0_Msk) == 0) return;
// Clear compare register 0 event
// Not the last statement, thus reduce risk of causing tail chaining back into the handler function
NRF_TIMER2->EVENTS_COMPARE[0] = 0;
NRF_TIMER2->CC[0] += 1000;
// The 5x5 LEDs are not individually controlled.
// Instead they are in 3 groups.
// If all 3 groups are set ON - and say pin 03 is ON, then 3 LEDs will light. Not the desired result.
// The trick is thus to have only one group ON at once and cycle through the groups quickly
// The LEDs are scattered throughout the 5x5 grid, so a bit of logic is required to find the right pin.
switch (nextGroup){
case 0:
// Turn off Group 26
pinMode(26, OUTPUT);
digitalWrite(26, LOW);
// Now focus on Group 27
// xx 23 xx 24 xx
// xx xx xx xx xx
// 04 xx 10 xx 03
// xx xx xx xx xx
// xx 09 xx 25 xx
screen[2][4] ? digitalWrite(3, LOW) : digitalWrite(3, HIGH);
screen[2][0] ? digitalWrite(4, LOW) : digitalWrite(4, HIGH);
digitalWrite(6, HIGH);
digitalWrite(7, HIGH);
screen[4][1] ? digitalWrite(9, LOW) : digitalWrite(9, HIGH);
screen[2][2] ? digitalWrite(10, LOW) : digitalWrite(10, HIGH);
screen[0][1] ? digitalWrite(23, LOW) : digitalWrite(23, HIGH);
screen[0][3] ? digitalWrite(24, LOW) : digitalWrite(24, HIGH);
screen[4][3] ? digitalWrite(25, LOW) : digitalWrite(25, HIGH);
// Turn on Group 27
pinMode(27, OUTPUT);
digitalWrite(27, HIGH);
nextGroup = 1;
break;
case 1:
// Turn off Group 27
pinMode(27, OUTPUT);
digitalWrite(27, LOW);
// Now focus on Group 28
// xx xx xx xx xx
// 23 24 25 09 07
// xx xx xx 06 xx
// xx xx xx xx xx
// 10 xx 03 xx 04
screen[4][2] ? digitalWrite(3, LOW) : digitalWrite(3, HIGH);
screen[4][4] ? digitalWrite(4, LOW) : digitalWrite(4, HIGH);
screen[2][3] ? digitalWrite(6, LOW) : digitalWrite(6, HIGH);
screen[1][4] ? digitalWrite(7, LOW) : digitalWrite(7, HIGH);
screen[1][3] ? digitalWrite(9, LOW) : digitalWrite(9, HIGH);
screen[4][0] ? digitalWrite(10, LOW) : digitalWrite(10, HIGH);
screen[1][0] ? digitalWrite(23, LOW) : digitalWrite(23, HIGH);
screen[1][1] ? digitalWrite(24, LOW) : digitalWrite(24, HIGH);
screen[1][2] ? digitalWrite(25, LOW) : digitalWrite(25, HIGH);
// Turn on Group 28
pinMode(28, OUTPUT);
digitalWrite(28, HIGH);
nextGroup = 2;
break;
case 2:
// Turn off Group 28
pinMode(28, OUTPUT);
digitalWrite(28, LOW);
// Now focus on Group 26
// 03 xx 04 xx 10
// xx xx xx xx xx
// xx 06 xx xx xx
// 07 09 25 25 23
// xx xx xx xx xx
screen[0][0] ? digitalWrite(3, LOW) : digitalWrite(3, HIGH);
screen[0][2] ? digitalWrite(4, LOW) : digitalWrite(4, HIGH);
screen[2][1] ? digitalWrite(6, LOW) : digitalWrite(6, HIGH);
screen[3][0] ? digitalWrite(7, LOW) : digitalWrite(7, HIGH);
screen[3][1] ? digitalWrite(9, LOW) : digitalWrite(9, HIGH);
screen[0][4] ? digitalWrite(10, LOW) : digitalWrite(10, HIGH);
screen[3][4] ? digitalWrite(23, LOW) : digitalWrite(23, HIGH);
screen[3][3] ? digitalWrite(24, LOW) : digitalWrite(24, HIGH);
screen[3][2] ? digitalWrite(25, LOW) : digitalWrite(25, HIGH);
// Turn on Group 26
pinMode(26, OUTPUT);
digitalWrite(26, HIGH);
nextGroup = 0;
break;
}
}
}
void configTimer2(void)
{
// Set the timer in Timer Mode
NRF_TIMER2->MODE = TIMER_MODE_MODE_Timer;
// Clear the task first to be usable for later
NRF_TIMER2->TASKS_CLEAR = 1;
// Nordic nRF51822 – 16 MHz 32-bit ARM Cortex-M0 microcontroller,
// Set the prescaler. We choose 4:
// Tick = 2^4/16,000,000 = 0.000001 seconds (1,000,000 ticks per second). 1Mhz.
// Prescaler accepts values from 0-9 only.
NRF_TIMER2->PRESCALER = 4;
// Set counter to 16 bit resolution. Timer is 16bit.
NRF_TIMER2->BITMODE = TIMER_BITMODE_BITMODE_16Bit;
// Set value for TIMER2 compare register 0
// The maximum compare value for 16 bits is 0xFFFF (= 65535)
// 1000 microseconds (above) = 1 millisecond
// Once reached it will fire off the first event
NRF_TIMER2->CC[0] = 1000;
// Enable interrupt on Timer 2, for a CC[0] match event
NRF_TIMER2->INTENSET = (TIMER_INTENSET_COMPARE0_Enabled << TIMER_INTENSET_COMPARE0_Pos);
// Enable the Interupt
NVIC_EnableIRQ(TIMER2_IRQn);
// Start TIMER2
NRF_TIMER2->TASKS_START = 1;
}
RoboticBoat.uk