master
Ondřej Hruška 7 years ago
parent edbe46703f
commit b20e5a9522
  1. 78
      README.md
  2. 13
      game.c
  3. 10
      lib/wsrgb.c
  4. 2
      lib/wsrgb.h
  5. 17
      main.c

@ -1,78 +1,8 @@
# AVR C Boilerplate
# Simon Says with Pro Mini
This is a basic boilerplate for programming AVRs in C.
Fun little project that has grown quite more than expected, at least on the hardware side.
The project aims to make programming Arduinos in C fun by
providing support for basic functionality like GPIO and USART,
so you can start developing without having the datasheet open
all the time.
There will be a proper log for this later, with schematics etc.
It is intended for **ATmega328P** (the chip in Arduinos),
but can be easily adapted to other parts.
For now, you can have a peek and thank heavens you don't have to understand any of it xD
## Requirements
Before you can start coding, you need to install a few software packages:
- `avrdude` - the flash tool
- `avr-gcc` - compiler
- `avr-libc` - libc implementation for AVR
- `avr-binutils` - utils for manipulating AVR binaries
- `make` - to run the Makefile
There's a good chance you already have `make`, the rest should be in your
distribution's repos.
If you're on Arch:
```
# pacman -S base-devel avr-gcc avr-binutils avr-libc avrdude
```
If you're on Mac, you should be able to pull the stuff with *brew*.
## Getting started
The provided `main.c` is a good starting point - it contains some simple demo code.
You can compile it with `make` and flash with `make flash`.
### Before you can flash
First, check that the `avrdude` options in the file are correct for your system - especially
the device and speed.
```ini
# AVRDUDE settings
PROG_BAUD = 57600
PROG_DEV = /dev/ttyUSB0
PROG_TYPE = arduino
# Build the final AVRDUDE arguments
PROG_ARGS = -c $(PROG_TYPE) -p $(MCU) -b $(PROG_BAUD) -P $(PROG_DEV)
```
- Adjust `PROG_DEV` to the device your board is connected to. On Linux it's usually
`/dev/ttyUSB0`, but it can also be `/dev/ttyACM0` or something else. On Mac, it'll be
`/dev/cu.xxx`. On Windows it's some `COMx`.<br>
Linux and Mac users can use `ls /dev` to see their devices. Windows users will find
this in their Device Manager.
- You may also adjust the baudrate (`PROG_BAUD`). Some boards need `115200`.
**TIP:** You can look what the Arduino IDE is using - it's running avrdude too.
### Adding new files
- If you *add a new C file* to the project, add an entry for it's `.o` (object file,
created by the compiler before linking) to the `OBJS` list in the Makefile.
- Similarly, if you *add a new folder with header files*, add it to `INCL_DIRS`.
- In case you need `printf` (or `printf` with floats), enable the appropriate LD_FLAGS
in the Makefile (it's well commented). Code size will - obviously - grow quite a bit.
## Notes
- The **Arduino UNO** bootloader has a quirk where `Double Speed Asynchronous Mode` for USART
is enabled by default, so if you set your baud rate to 9600, you'd really get 19200.<br>
We correct this in the `usart_init()` function to keep things consistent and to avoid
confusion.<br>
*If you wish to turn this on* however, you can do so by using `usart_set_2x(true)`.

@ -58,6 +58,8 @@ enum GameState_enum {
/** Current game state */
enum GameState_enum GameState = STATE_NEW_GAME;
volatile bool holding_new_game_button = false;
/** Screen colors */
uint32_t screen[4] = {0, 0, 0, 0};
const uint32_t brt[4] = {C_BRT1, C_BRT2, C_BRT3, C_BRT4};
@ -125,6 +127,9 @@ suc:
/** Enter state - callback for delayed state change */
void deferred_enter_state(void *state)
{
// clear flag that button was held
holding_new_game_button = false;
enter_state((enum GameState_enum) state);
}
@ -261,8 +266,8 @@ void game_main(void)
while (1) {
if (GameState == last_state) {
if (GameState == STATE_NEW_GAME) {
if (cnt == 50) {
// clear after 5 secs
if (cnt == 20 && !holding_new_game_button) {
// clear after 2 secs
display_show(SEG_G, SEG_G);
}
@ -275,9 +280,10 @@ void game_main(void)
show_screen();
delay_s(2000);
pin_down(PIN_PWR_HOLD);
while(1); // wait for shutdown
}
} else {
if (cnt > 150) {// 15 secs = stop game.
if (cnt > 120) {// 12 secs = stop game.
// reset state
enter_state(STATE_NEW_GAME);
show_screen();
@ -310,6 +316,7 @@ void game_button_handler(uint8_t button, bool press)
if (press) {
// feedback
display_show_number(0); // show 0
holding_new_game_button = true;
}
if (!press) { // released

@ -11,6 +11,8 @@
/* Driver code for WS2812B */
volatile bool ws_no_cli_sei = false;
void ws_init()
{
as_output(WS_PIN);
@ -72,27 +74,27 @@ void ws_send_rgb24(rgb24_t rgb)
/** Send array of colors */
void ws_send_xrgb_array(const xrgb_t rgbs[], const uint8_t length)
{
cli();
if (!ws_no_cli_sei) cli();
for (uint8_t i = 0; i < length; i++) {
const xrgb_t c = rgbs[i];
ws_send_byte(c.g);
ws_send_byte(c.r);
ws_send_byte(c.b);
}
sei();
if (!ws_no_cli_sei) sei();
}
/** Send array of colors */
void ws_send_rgb24_array(const rgb24_t rgbs[], const uint8_t length)
{
cli();
if (!ws_no_cli_sei) cli();
for (uint8_t i = 0; i < length; i++) {
const rgb24_t c = rgbs[i];
ws_send_byte(rgb24_g(c));
ws_send_byte(rgb24_r(c));
ws_send_byte(rgb24_b(c));
}
sei();
if (!ws_no_cli_sei) sei();
}
//#define ws_send_rgb24_array(rgbs, length) __ws_send_array_proto((rgbs), (length), rgb24)

@ -21,6 +21,8 @@
// --- functions for RGB strips ---
extern volatile bool ws_no_cli_sei;
/** Initialize OI */
void ws_init();

@ -127,9 +127,26 @@ void task_check_shutdown_btn(void *unused) {
if (debo_get_pin(0) // 0 - first
&& !booting
&& (time_ms - time_pwr_pressed > 1000)) {
cli();
ws_no_cli_sei = true;
usart_puts("Power OFF\r\n");
uint32_t zeros[4] = {0,0,0,0};
leds_set(zeros);
leds_show();
display_show(0,0);
_delay_ms(100);
// Wait for user to release
while (pin_read(PIN_PWR_KEY));
_delay_ms(500);
// shut down
pin_down(PIN_PWR_HOLD);
// wait for shutdown
while(1);
}
}

Loading…
Cancel
Save