cleaning, moved memgame to projects

pull/1/head
Ondřej Hruška 9 years ago
parent c96cdbe66d
commit f2cdba327c
  1. 1
      .gitignore
  2. 1
      devel/memorygame/lib
  3. 973
      devel/memorygame/main.pre
  4. 0
      devel/moo/Makefile
  5. 1
      devel/moo/lib
  6. 22
      devel/moo/main.c
  7. 166
      projects/color-memory-game/Makefile
  8. 31
      projects/color-memory-game/README.md
  9. 6
      projects/color-memory-game/lib/README.md
  10. 39
      projects/color-memory-game/lib/adc.h
  11. 42
      projects/color-memory-game/lib/arduino_pins.h
  12. 46
      projects/color-memory-game/lib/calc.h
  13. 83
      projects/color-memory-game/lib/colors.h
  14. 104
      projects/color-memory-game/lib/debounce.h
  15. 6
      projects/color-memory-game/lib/meta.h
  16. 18
      projects/color-memory-game/lib/nsdelay.h
  17. 107
      projects/color-memory-game/lib/pins.h
  18. 98
      projects/color-memory-game/lib/ws2812.h
  19. 403
      projects/color-memory-game/main.c

1
.gitignore vendored

@ -3,6 +3,7 @@
*.obj
*.elf
*.lst
*.pre
*~
*.bak
*.lib

@ -1,973 +0,0 @@
# 1 "main.c"
# 1 "/home/ondra/git/avr-projects/devel/memorygame//"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "main.c"
# 1 "/usr/avr/include/avr/io.h" 1 3
# 99 "/usr/avr/include/avr/io.h" 3
# 1 "/usr/avr/include/avr/sfr_defs.h" 1 3
# 126 "/usr/avr/include/avr/sfr_defs.h" 3
# 1 "/usr/avr/include/inttypes.h" 1 3
# 37 "/usr/avr/include/inttypes.h" 3
# 1 "/usr/lib/gcc/avr/4.9.2/include/stdint.h" 1 3 4
# 9 "/usr/lib/gcc/avr/4.9.2/include/stdint.h" 3 4
# 1 "/usr/avr/include/stdint.h" 1 3 4
# 122 "/usr/avr/include/stdint.h" 3 4
typedef signed int int8_t __attribute__((__mode__(__QI__)));
typedef unsigned int uint8_t __attribute__((__mode__(__QI__)));
typedef signed int int16_t __attribute__ ((__mode__ (__HI__)));
typedef unsigned int uint16_t __attribute__ ((__mode__ (__HI__)));
typedef signed int int32_t __attribute__ ((__mode__ (__SI__)));
typedef unsigned int uint32_t __attribute__ ((__mode__ (__SI__)));
typedef signed int int64_t __attribute__((__mode__(__DI__)));
typedef unsigned int uint64_t __attribute__((__mode__(__DI__)));
# 143 "/usr/avr/include/stdint.h" 3 4
typedef int16_t intptr_t;
typedef uint16_t uintptr_t;
# 160 "/usr/avr/include/stdint.h" 3 4
typedef int8_t int_least8_t;
typedef uint8_t uint_least8_t;
typedef int16_t int_least16_t;
typedef uint16_t uint_least16_t;
typedef int32_t int_least32_t;
typedef uint32_t uint_least32_t;
typedef int64_t int_least64_t;
typedef uint64_t uint_least64_t;
# 214 "/usr/avr/include/stdint.h" 3 4
typedef int8_t int_fast8_t;
typedef uint8_t uint_fast8_t;
typedef int16_t int_fast16_t;
typedef uint16_t uint_fast16_t;
typedef int32_t int_fast32_t;
typedef uint32_t uint_fast32_t;
typedef int64_t int_fast64_t;
typedef uint64_t uint_fast64_t;
# 274 "/usr/avr/include/stdint.h" 3 4
typedef int64_t intmax_t;
typedef uint64_t uintmax_t;
# 10 "/usr/lib/gcc/avr/4.9.2/include/stdint.h" 2 3 4
# 38 "/usr/avr/include/inttypes.h" 2 3
# 77 "/usr/avr/include/inttypes.h" 3
typedef int32_t int_farptr_t;
typedef uint32_t uint_farptr_t;
# 127 "/usr/avr/include/avr/sfr_defs.h" 2 3
# 100 "/usr/avr/include/avr/io.h" 2 3
# 248 "/usr/avr/include/avr/io.h" 3
# 1 "/usr/avr/include/avr/iom328p.h" 1 3
# 249 "/usr/avr/include/avr/io.h" 2 3
# 534 "/usr/avr/include/avr/io.h" 3
# 1 "/usr/avr/include/avr/portpins.h" 1 3
# 535 "/usr/avr/include/avr/io.h" 2 3
# 1 "/usr/avr/include/avr/common.h" 1 3
# 537 "/usr/avr/include/avr/io.h" 2 3
# 1 "/usr/avr/include/avr/version.h" 1 3
# 539 "/usr/avr/include/avr/io.h" 2 3
# 1 "/usr/avr/include/avr/fuse.h" 1 3
# 239 "/usr/avr/include/avr/fuse.h" 3
typedef struct
{
unsigned char low;
unsigned char high;
unsigned char extended;
} __fuse_t;
# 546 "/usr/avr/include/avr/io.h" 2 3
# 1 "/usr/avr/include/avr/lock.h" 1 3
# 549 "/usr/avr/include/avr/io.h" 2 3
# 2 "main.c" 2
# 1 "/usr/avr/include/avr/interrupt.h" 1 3
# 3 "main.c" 2
# 1 "/usr/avr/include/util/delay.h" 1 3
# 43 "/usr/avr/include/util/delay.h" 3
# 1 "/usr/avr/include/util/delay_basic.h" 1 3
# 40 "/usr/avr/include/util/delay_basic.h" 3
static inline void _delay_loop_1(uint8_t __count) __attribute__((always_inline));
static inline void _delay_loop_2(uint16_t __count) __attribute__((always_inline));
# 80 "/usr/avr/include/util/delay_basic.h" 3
void
_delay_loop_1(uint8_t __count)
{
__asm__ volatile (
"1: dec %0" "\n\t"
"brne 1b"
: "=r" (__count)
: "0" (__count)
);
}
# 102 "/usr/avr/include/util/delay_basic.h" 3
void
_delay_loop_2(uint16_t __count)
{
__asm__ volatile (
"1: sbiw %0,1" "\n\t"
"brne 1b"
: "=w" (__count)
: "0" (__count)
);
}
# 44 "/usr/avr/include/util/delay.h" 2 3
# 1 "/usr/avr/include/math.h" 1 3
# 127 "/usr/avr/include/math.h" 3
extern double cos(double __x) __attribute__((__const__));
extern double sin(double __x) __attribute__((__const__));
extern double tan(double __x) __attribute__((__const__));
extern double fabs(double __x) __attribute__((__const__));
extern double fmod(double __x, double __y) __attribute__((__const__));
# 168 "/usr/avr/include/math.h" 3
extern double modf(double __x, double *__iptr);
extern float modff (float __x, float *__iptr);
extern double sqrt(double __x) __attribute__((__const__));
extern float sqrtf (float) __attribute__((__const__));
extern double cbrt(double __x) __attribute__((__const__));
# 194 "/usr/avr/include/math.h" 3
extern double hypot (double __x, double __y) __attribute__((__const__));
extern double square(double __x) __attribute__((__const__));
extern double floor(double __x) __attribute__((__const__));
extern double ceil(double __x) __attribute__((__const__));
# 234 "/usr/avr/include/math.h" 3
extern double frexp(double __x, int *__pexp);
extern double ldexp(double __x, int __exp) __attribute__((__const__));
extern double exp(double __x) __attribute__((__const__));
extern double cosh(double __x) __attribute__((__const__));
extern double sinh(double __x) __attribute__((__const__));
extern double tanh(double __x) __attribute__((__const__));
extern double acos(double __x) __attribute__((__const__));
extern double asin(double __x) __attribute__((__const__));
extern double atan(double __x) __attribute__((__const__));
# 298 "/usr/avr/include/math.h" 3
extern double atan2(double __y, double __x) __attribute__((__const__));
extern double log(double __x) __attribute__((__const__));
extern double log10(double __x) __attribute__((__const__));
extern double pow(double __x, double __y) __attribute__((__const__));
extern int isnan(double __x) __attribute__((__const__));
# 333 "/usr/avr/include/math.h" 3
extern int isinf(double __x) __attribute__((__const__));
__attribute__((__const__)) static inline int isfinite (double __x)
{
unsigned char __exp;
__asm__ (
"mov %0, %C1 \n\t"
"lsl %0 \n\t"
"mov %0, %D1 \n\t"
"rol %0 "
: "=r" (__exp)
: "r" (__x) );
return __exp != 0xff;
}
__attribute__((__const__)) static inline double copysign (double __x, double __y)
{
__asm__ (
"bst %D2, 7 \n\t"
"bld %D0, 7 "
: "=r" (__x)
: "0" (__x), "r" (__y) );
return __x;
}
# 376 "/usr/avr/include/math.h" 3
extern int signbit (double __x) __attribute__((__const__));
extern double fdim (double __x, double __y) __attribute__((__const__));
# 392 "/usr/avr/include/math.h" 3
extern double fma (double __x, double __y, double __z) __attribute__((__const__));
extern double fmax (double __x, double __y) __attribute__((__const__));
extern double fmin (double __x, double __y) __attribute__((__const__));
extern double trunc (double __x) __attribute__((__const__));
# 426 "/usr/avr/include/math.h" 3
extern double round (double __x) __attribute__((__const__));
# 439 "/usr/avr/include/math.h" 3
extern long lround (double __x) __attribute__((__const__));
# 453 "/usr/avr/include/math.h" 3
extern long lrint (double __x) __attribute__((__const__));
# 45 "/usr/avr/include/util/delay.h" 2 3
# 84 "/usr/avr/include/util/delay.h" 3
static inline void _delay_us(double __us) __attribute__((always_inline));
static inline void _delay_ms(double __ms) __attribute__((always_inline));
# 141 "/usr/avr/include/util/delay.h" 3
void
_delay_ms(double __ms)
{
double __tmp ;
# 166 "/usr/avr/include/util/delay.h" 3
uint16_t __ticks;
__tmp = ((16000000UL) / 4e3) * __ms;
if (__tmp < 1.0)
__ticks = 1;
else if (__tmp > 65535)
{
__ticks = (uint16_t) (__ms * 10.0);
while(__ticks)
{
_delay_loop_2(((16000000UL) / 4e3) / 10);
__ticks --;
}
return;
}
else
__ticks = (uint16_t)__tmp;
_delay_loop_2(__ticks);
}
# 223 "/usr/avr/include/util/delay.h" 3
void
_delay_us(double __us)
{
double __tmp ;
# 248 "/usr/avr/include/util/delay.h" 3
uint8_t __ticks;
double __tmp2 ;
__tmp = ((16000000UL) / 3e6) * __us;
__tmp2 = ((16000000UL) / 4e6) * __us;
if (__tmp < 1.0)
__ticks = 1;
else if (__tmp2 > 65535)
{
_delay_ms(__us / 1000.0);
}
else if (__tmp > 255)
{
uint16_t __ticks=(uint16_t)__tmp2;
_delay_loop_2(__ticks);
return;
}
else
__ticks = (uint8_t)__tmp;
_delay_loop_1(__ticks);
}
# 4 "main.c" 2
# 1 "/usr/avr/include/stdlib.h" 1 3
# 47 "/usr/avr/include/stdlib.h" 3
# 1 "/usr/lib/gcc/avr/4.9.2/include/stddef.h" 1 3 4
# 212 "/usr/lib/gcc/avr/4.9.2/include/stddef.h" 3 4
typedef unsigned int size_t;
# 324 "/usr/lib/gcc/avr/4.9.2/include/stddef.h" 3 4
typedef int wchar_t;
# 48 "/usr/avr/include/stdlib.h" 2 3
# 68 "/usr/avr/include/stdlib.h" 3
typedef struct {
int quot;
int rem;
} div_t;
typedef struct {
long quot;
long rem;
} ldiv_t;
typedef int (*__compar_fn_t)(const void *, const void *);
# 114 "/usr/avr/include/stdlib.h" 3
extern void abort(void) __attribute__((__noreturn__));
extern int abs(int __i) __attribute__((__const__));
# 128 "/usr/avr/include/stdlib.h" 3
extern long labs(long __i) __attribute__((__const__));
# 151 "/usr/avr/include/stdlib.h" 3
extern void *bsearch(const void *__key, const void *__base, size_t __nmemb,
size_t __size, int (*__compar)(const void *, const void *));
extern div_t div(int __num, int __denom) __asm__("__divmodhi4") __attribute__((__const__));
extern ldiv_t ldiv(long __num, long __denom) __asm__("__divmodsi4") __attribute__((__const__));
# 183 "/usr/avr/include/stdlib.h" 3
extern void qsort(void *__base, size_t __nmemb, size_t __size,
__compar_fn_t __compar);
# 216 "/usr/avr/include/stdlib.h" 3
extern long strtol(const char *__nptr, char **__endptr, int __base);
# 250 "/usr/avr/include/stdlib.h" 3
extern unsigned long strtoul(const char *__nptr, char **__endptr, int __base);
# 262 "/usr/avr/include/stdlib.h" 3
extern long atol(const char *__s) __attribute__((__pure__));
# 274 "/usr/avr/include/stdlib.h" 3
extern int atoi(const char *__s) __attribute__((__pure__));
# 286 "/usr/avr/include/stdlib.h" 3
extern void exit(int __status) __attribute__((__noreturn__));
# 298 "/usr/avr/include/stdlib.h" 3
extern void *malloc(size_t __size) __attribute__((__malloc__));
extern void free(void *__ptr);
extern size_t __malloc_margin;
extern char *__malloc_heap_start;
extern char *__malloc_heap_end;
extern void *calloc(size_t __nele, size_t __size) __attribute__((__malloc__));
# 346 "/usr/avr/include/stdlib.h" 3
extern void *realloc(void *__ptr, size_t __size) __attribute__((__malloc__));
extern double strtod(const char *__nptr, char **__endptr);
extern double atof(const char *__nptr);
# 372 "/usr/avr/include/stdlib.h" 3
extern int rand(void);
extern void srand(unsigned int __seed);
extern int rand_r(unsigned long *__ctx);
# 417 "/usr/avr/include/stdlib.h" 3
extern __inline__ __attribute__((__gnu_inline__))
char *itoa (int __val, char *__s, int __radix)
{
if (!__builtin_constant_p (__radix)) {
extern char *__itoa (int, char *, int);
return __itoa (__val, __s, __radix);
} else if (__radix < 2 || __radix > 36) {
*__s = 0;
return __s;
} else {
extern char *__itoa_ncheck (int, char *, unsigned char);
return __itoa_ncheck (__val, __s, __radix);
}
}
# 462 "/usr/avr/include/stdlib.h" 3
extern __inline__ __attribute__((__gnu_inline__))
char *ltoa (long __val, char *__s, int __radix)
{
if (!__builtin_constant_p (__radix)) {
extern char *__ltoa (long, char *, int);
return __ltoa (__val, __s, __radix);
} else if (__radix < 2 || __radix > 36) {
*__s = 0;
return __s;
} else {
extern char *__ltoa_ncheck (long, char *, unsigned char);
return __ltoa_ncheck (__val, __s, __radix);
}
}
# 505 "/usr/avr/include/stdlib.h" 3
extern __inline__ __attribute__((__gnu_inline__))
char *utoa (unsigned int __val, char *__s, int __radix)
{
if (!__builtin_constant_p (__radix)) {
extern char *__utoa (unsigned int, char *, int);
return __utoa (__val, __s, __radix);
} else if (__radix < 2 || __radix > 36) {
*__s = 0;
return __s;
} else {
extern char *__utoa_ncheck (unsigned int, char *, unsigned char);
return __utoa_ncheck (__val, __s, __radix);
}
}
# 547 "/usr/avr/include/stdlib.h" 3
extern __inline__ __attribute__((__gnu_inline__))
char *ultoa (unsigned long __val, char *__s, int __radix)
{
if (!__builtin_constant_p (__radix)) {
extern char *__ultoa (unsigned long, char *, int);
return __ultoa (__val, __s, __radix);
} else if (__radix < 2 || __radix > 36) {
*__s = 0;
return __s;
} else {
extern char *__ultoa_ncheck (unsigned long, char *, unsigned char);
return __ultoa_ncheck (__val, __s, __radix);
}
}
# 579 "/usr/avr/include/stdlib.h" 3
extern long random(void);
extern void srandom(unsigned long __seed);
extern long random_r(unsigned long *__ctx);
# 638 "/usr/avr/include/stdlib.h" 3
extern char *dtostre(double __val, char *__s, unsigned char __prec,
unsigned char __flags);
# 655 "/usr/avr/include/stdlib.h" 3
extern char *dtostrf(double __val, signed char __width,
unsigned char __prec, char *__s);
# 672 "/usr/avr/include/stdlib.h" 3
extern int atexit(void (*)(void));
extern int system (const char *);
extern char *getenv (const char *);
# 7 "main.c" 2
# 1 "lib/meta.h" 1
# 9 "main.c" 2
# 1 "lib/arduino_pins.h" 1
# 1 "lib/pins.h" 1
# 30 "lib/pins.h"
# 1 "lib/calc.h" 1
# 31 "lib/pins.h" 2
# 51 "lib/pins.h"
typedef volatile uint8_t* PORT_P;
typedef uint8_t BIT_N;
# 8 "lib/arduino_pins.h" 2
# 10 "main.c" 2
# 1 "lib/colors.h" 1
typedef struct {
uint8_t r;
uint8_t g;
uint8_t b;
} xrgb_t;
typedef uint32_t rgb24_t;
typedef uint16_t rgb16_t;
typedef uint16_t rgb12_t;
typedef uint8_t rgb6_t;
# 12 "main.c" 2
# 1 "lib/ws2812.h" 1
# 15 "lib/ws2812.h"
# 1 "/usr/avr/include/avr/cpufunc.h" 1 3
# 16 "lib/ws2812.h" 2
# 1 "lib/nsdelay.h" 1
# 19 "lib/ws2812.h" 2
# 13 "main.c" 2
# 1 "lib/adc.h" 1
# 1 "/usr/lib/gcc/avr/4.9.2/include/stdbool.h" 1 3 4
# 5 "lib/adc.h" 2
void adc_init()
{
(*(volatile uint8_t *)(0x7A)) |= (1 << (2)) | (1 << (1)) | (1 << (0));
(*(volatile uint8_t *)(0x7C)) |= (1 << (6));
do { ((*(volatile uint8_t *)(0x7A))) |= (1 << (uint8_t)(7)); } while(0);
}
uint8_t adc_read_byte(uint8_t channel)
{
do { ((*(volatile uint8_t *)(0x7C))) = (((*(volatile uint8_t *)(0x7C))) & 0xF0) | ((uint8_t)(channel) & 0xF); } while(0);
do { ((*(volatile uint8_t *)(0x7C))) |= (1 << (uint8_t)(5)); } while(0);
do { ((*(volatile uint8_t *)(0x7A))) |= (1 << (uint8_t)(6)); } while(0);
while(((((uint8_t)((*(volatile uint8_t *)(0x7A)))) >> (uint8_t)(6)) & 0x1));
return (*(volatile uint8_t *)(0x79));
}
uint16_t adc_read_word(uint8_t channel)
{
do { ((*(volatile uint8_t *)(0x7C))) = (((*(volatile uint8_t *)(0x7C))) & 0xF0) | ((uint8_t)(channel) & 0xF); } while(0);
do { ((*(volatile uint8_t *)(0x7C))) &= ~(1 << (uint8_t)(5)); } while(0);
do { ((*(volatile uint8_t *)(0x7A))) |= (1 << (uint8_t)(6)); } while(0);
while(((((uint8_t)((*(volatile uint8_t *)(0x7A)))) >> (uint8_t)(6)) & 0x1));
return (*(volatile uint16_t *)(0x78));
}
# 14 "main.c" 2
# 1 "lib/debounce.h" 1
# 51 "lib/debounce.h"
typedef struct {
PORT_P reg;
uint8_t bit;
uint8_t count;
} debo_slot_t;
debo_slot_t debo_slots[6];
uint8_t debo_next_slot = 0;
uint8_t debo_register(PORT_P reg, uint8_t bit, _Bool invert)
{
debo_slots[debo_next_slot] = (debo_slot_t){
.reg = reg,
.bit = bit | ((invert & 1) << 7) | (((*(reg) >> (uint8_t)(bit)) & 0x1) << 6),
.count = 0,
};
return debo_next_slot++;
}
void debo_tick()
{
for (uint8_t i = 0; i < debo_next_slot; i++) {
_Bool value = ((*(debo_slots[i].reg) >> (uint8_t)(debo_slots[i].bit & 0x7)) & 0x1);
if (value != ((((uint8_t)(debo_slots[i].bit)) >> (uint8_t)(6)) & 0x1)) {
if (debo_slots[i].count < 1) {
debo_slots[i].count++;
} else {
do { (debo_slots[i].bit) = ((debo_slots[i].bit) & ~(1 << (uint8_t)(6))) | (((uint8_t)(value) & 0x1) << (uint8_t)(6)); } while(0);
debo_slots[i].count = 0;
}
} else {
debo_slots[i].count = 0;
}
}
}
# 19 "main.c" 2
const xrgb_t COLORS[] = {
{ .r = ((uint8_t)(((((rgb24_t) (0xB14835)) >> 16) & 0xFF))), .g = ((uint8_t)(((((rgb24_t) (0xB14835)) >> 8) & 0xFF))), .b = ((uint8_t)(((((rgb24_t) (0xB14835)) >> 0) & 0xFF))) },
{ .r = ((uint8_t)(((((rgb24_t) (0x4C1661)) >> 16) & 0xFF))), .g = ((uint8_t)(((((rgb24_t) (0x4C1661)) >> 8) & 0xFF))), .b = ((uint8_t)(((((rgb24_t) (0x4C1661)) >> 0) & 0xFF))) },
{ .r = ((uint8_t)(((((rgb24_t) (0xA3268E)) >> 16) & 0xFF))), .g = ((uint8_t)(((((rgb24_t) (0xA3268E)) >> 8) & 0xFF))), .b = ((uint8_t)(((((rgb24_t) (0xA3268E)) >> 0) & 0xFF))) },
{ .r = ((uint8_t)(((((rgb24_t) (0x009ADA)) >> 16) & 0xFF))), .g = ((uint8_t)(((((rgb24_t) (0x009ADA)) >> 8) & 0xFF))), .b = ((uint8_t)(((((rgb24_t) (0x009ADA)) >> 0) & 0xFF))) },
{ .r = ((uint8_t)(((((rgb24_t) (0x007D8F)) >> 16) & 0xFF))), .g = ((uint8_t)(((((rgb24_t) (0x007D8F)) >> 8) & 0xFF))), .b = ((uint8_t)(((((rgb24_t) (0x007D8F)) >> 0) & 0xFF))) },
{ .r = ((uint8_t)(((((rgb24_t) (0x002E5A)) >> 16) & 0xFF))), .g = ((uint8_t)(((((rgb24_t) (0x002E5A)) >> 8) & 0xFF))), .b = ((uint8_t)(((((rgb24_t) (0x002E5A)) >> 0) & 0xFF))) },
{ .r = ((uint8_t)(((((rgb24_t) (0x56BCC1)) >> 16) & 0xFF))), .g = ((uint8_t)(((((rgb24_t) (0x56BCC1)) >> 8) & 0xFF))), .b = ((uint8_t)(((((rgb24_t) (0x56BCC1)) >> 0) & 0xFF))) },
{ .r = ((uint8_t)(((((rgb24_t) (0x01654D)) >> 16) & 0xFF))), .g = ((uint8_t)(((((rgb24_t) (0x01654D)) >> 8) & 0xFF))), .b = ((uint8_t)(((((rgb24_t) (0x01654D)) >> 0) & 0xFF))) },
{ .r = ((uint8_t)(((((rgb24_t) (0xF5864F)) >> 16) & 0xFF))), .g = ((uint8_t)(((((rgb24_t) (0xF5864F)) >> 8) & 0xFF))), .b = ((uint8_t)(((((rgb24_t) (0xF5864F)) >> 0) & 0xFF))) },
{ .r = ((uint8_t)(((((rgb24_t) (0xED1B24)) >> 16) & 0xFF))), .g = ((uint8_t)(((((rgb24_t) (0xED1B24)) >> 8) & 0xFF))), .b = ((uint8_t)(((((rgb24_t) (0xED1B24)) >> 0) & 0xFF))) },
{ .r = ((uint8_t)(((((rgb24_t) (0xFDAF17)) >> 16) & 0xFF))), .g = ((uint8_t)(((((rgb24_t) (0xFDAF17)) >> 8) & 0xFF))), .b = ((uint8_t)(((((rgb24_t) (0xFDAF17)) >> 0) & 0xFF))) },
{ .r = ((uint8_t)(((((rgb24_t) (0xF58F83)) >> 16) & 0xFF))), .g = ((uint8_t)(((((rgb24_t) (0xF58F83)) >> 8) & 0xFF))), .b = ((uint8_t)(((((rgb24_t) (0xF58F83)) >> 0) & 0xFF))) },
{ .r = ((uint8_t)(((((rgb24_t) (0xED008C)) >> 16) & 0xFF))), .g = ((uint8_t)(((((rgb24_t) (0xED008C)) >> 8) & 0xFF))), .b = ((uint8_t)(((((rgb24_t) (0xED008C)) >> 0) & 0xFF))) },
{ .r = ((uint8_t)(((((rgb24_t) (0xFEF200)) >> 16) & 0xFF))), .g = ((uint8_t)(((((rgb24_t) (0xFEF200)) >> 8) & 0xFF))), .b = ((uint8_t)(((((rgb24_t) (0xFEF200)) >> 0) & 0xFF))) },
{ .r = ((uint8_t)(((((rgb24_t) (0x6D9346)) >> 16) & 0xFF))), .g = ((uint8_t)(((((rgb24_t) (0x6D9346)) >> 8) & 0xFF))), .b = ((uint8_t)(((((rgb24_t) (0x6D9346)) >> 0) & 0xFF))) },
};
# 73 "main.c"
void render();
void update();
void __attribute__((naked, used, section(".init8"))) init()
{
do { ((*(volatile uint8_t *)((0x04) + 0x20))) |= (1 << (uint8_t)((2))); } while(0);
do { do { ((*(volatile uint8_t *)((0x0A) + 0x20))) &= ~(1 << (uint8_t)((2))); } while(0); do { ((*(volatile uint8_t *)((0x0B) + 0x20))) |= (1 << (uint8_t)((2))); } while(0); } while(0);
do { do { ((*(volatile uint8_t *)((0x0A) + 0x20))) &= ~(1 << (uint8_t)((3))); } while(0); do { ((*(volatile uint8_t *)((0x0B) + 0x20))) |= (1 << (uint8_t)((3))); } while(0); } while(0);
do { do { ((*(volatile uint8_t *)((0x0A) + 0x20))) &= ~(1 << (uint8_t)((4))); } while(0); do { ((*(volatile uint8_t *)((0x0B) + 0x20))) |= (1 << (uint8_t)((4))); } while(0); } while(0);
do { do { ((*(volatile uint8_t *)((0x0A) + 0x20))) &= ~(1 << (uint8_t)((5))); } while(0); do { ((*(volatile uint8_t *)((0x0B) + 0x20))) |= (1 << (uint8_t)((5))); } while(0); } while(0);
do { do { ((*(volatile uint8_t *)((0x0A) + 0x20))) &= ~(1 << (uint8_t)((6))); } while(0); do { ((*(volatile uint8_t *)((0x0B) + 0x20))) |= (1 << (uint8_t)((6))); } while(0); } while(0);
do { do { ((*(volatile uint8_t *)((0x0A) + 0x20))) &= ~(1 << (uint8_t)((7))); } while(0); do { ((*(volatile uint8_t *)((0x0B) + 0x20))) |= (1 << (uint8_t)((7))); } while(0); } while(0);
debo_register(&(*(volatile uint8_t *)((0x09) + 0x20)), 2, 1);
debo_register(&(*(volatile uint8_t *)((0x09) + 0x20)), 3, 1);
debo_register(&(*(volatile uint8_t *)((0x09) + 0x20)), 4, 1);
debo_register(&(*(volatile uint8_t *)((0x09) + 0x20)), 5, 1);
debo_register(&(*(volatile uint8_t *)((0x09) + 0x20)), 6, 1);
debo_register(&(*(volatile uint8_t *)((0x09) + 0x20)), 7, 1);
(*(volatile uint8_t *)((0x24) + 0x20)) = (1 << (1));
(*(volatile uint8_t *)((0x25) + 0x20)) = (1 << (2)) | (1 << (0));
(*(volatile uint8_t *)((0x27) + 0x20)) = 156;
do { ((*(volatile uint8_t *)(0x6E))) |= (1 << (uint8_t)(1)); } while(0);
__asm__ __volatile__ ("sei" ::: "memory");
}
void __vector_14 (void) __attribute__ ((signal,used, externally_visible)) ; void __vector_14 (void)
{
update();
render();
}
void main()
{
while(1);
}
typedef enum {
SECRET,
REVEALED,
GONE
} tilestate_t;
typedef struct {
uint8_t color;
tilestate_t state;
} tile_t;
tile_t board[(6 * 5)];
uint8_t cursor = 0;
volatile uint8_t noise = 0;
uint16_t xxx = 0;
void update()
{
if(xxx++ >= 100) {
noise = adc_read_byte(0);
xxx = 0;
}
}
xrgb_t screen[(6 * 5)];
void render()
{
const rgb24_t BLUE = 0x005397;
const rgb24_t RED = 0xFF0000;
const rgb24_t YELLOW = 0xFFFF00;
const rgb24_t BLACK = 0x000000;
rgb24_t c;
for (uint8_t i = 0; i < (6 * 5); i++) {
c = YELLOW;
if (i < 8) {
c = ((((uint8_t)(noise)) >> (uint8_t)(i)) & 0x1) ? RED : BLUE;
}
do { do { for (volatile int8_t __wsba_i = 7; __wsba_i >= 0; --__wsba_i) { if ((((((rgb24_t) (c)) >> 8) & 0xFF)) & (1 << __wsba_i)) { __asm__ __volatile__("":::"memory"); do { ((*(volatile uint8_t *)((0x05) + 0x20))) |= (1 << (uint8_t)((2))); } while(0); (((( (700) / (1000000000L / (signed long) 16000000UL) ) + (-2)) > 0) ? __builtin_avr_delay_cycles(( (700) / (1000000000L / (signed long) 16000000UL) ) + (-2)) : __builtin_avr_delay_cycles(0)); __asm__ __volatile__("":::"memory"); do { ((*(volatile uint8_t *)((0x05) + 0x20))) &= ~(1 << (uint8_t)((2))); } while(0); (((( (150) / (1000000000L / (signed long) 16000000UL) ) + (-10)) > 0) ? __builtin_avr_delay_cycles(( (150) / (1000000000L / (signed long) 16000000UL) ) + (-10)) : __builtin_avr_delay_cycles(0)); } else { __asm__ __volatile__("":::"memory"); do { ((*(volatile uint8_t *)((0x05) + 0x20))) |= (1 << (uint8_t)((2))); } while(0); (((( (150) / (1000000000L / (signed long) 16000000UL) ) + (-2)) > 0) ? __builtin_avr_delay_cycles(( (150) / (1000000000L / (signed long) 16000000UL) ) + (-2)) : __builtin_avr_delay_cycles(0)); __asm__ __volatile__("":::"memory"); do { ((*(volatile uint8_t *)((0x05) + 0x20))) &= ~(1 << (uint8_t)((2))); } while(0); (((( (700) / (1000000000L / (signed long) 16000000UL) ) + (-10)) > 0) ? __builtin_avr_delay_cycles(( (700) / (1000000000L / (signed long) 16000000UL) ) + (-10)) : __builtin_avr_delay_cycles(0)); } } } while(0); do { for (volatile int8_t __wsba_i = 7; __wsba_i >= 0; --__wsba_i) { if ((((((rgb24_t) (c)) >> 16) & 0xFF)) & (1 << __wsba_i)) { __asm__ __volatile__("":::"memory"); do { ((*(volatile uint8_t *)((0x05) + 0x20))) |= (1 << (uint8_t)((2))); } while(0); (((( (700) / (1000000000L / (signed long) 16000000UL) ) + (-2)) > 0) ? __builtin_avr_delay_cycles(( (700) / (1000000000L / (signed long) 16000000UL) ) + (-2)) : __builtin_avr_delay_cycles(0)); __asm__ __volatile__("":::"memory"); do { ((*(volatile uint8_t *)((0x05) + 0x20))) &= ~(1 << (uint8_t)((2))); } while(0); (((( (150) / (1000000000L / (signed long) 16000000UL) ) + (-10)) > 0) ? __builtin_avr_delay_cycles(( (150) / (1000000000L / (signed long) 16000000UL) ) + (-10)) : __builtin_avr_delay_cycles(0)); } else { __asm__ __volatile__("":::"memory"); do { ((*(volatile uint8_t *)((0x05) + 0x20))) |= (1 << (uint8_t)((2))); } while(0); (((( (150) / (1000000000L / (signed long) 16000000UL) ) + (-2)) > 0) ? __builtin_avr_delay_cycles(( (150) / (1000000000L / (signed long) 16000000UL) ) + (-2)) : __builtin_avr_delay_cycles(0)); __asm__ __volatile__("":::"memory"); do { ((*(volatile uint8_t *)((0x05) + 0x20))) &= ~(1 << (uint8_t)((2))); } while(0); (((( (700) / (1000000000L / (signed long) 16000000UL) ) + (-10)) > 0) ? __builtin_avr_delay_cycles(( (700) / (1000000000L / (signed long) 16000000UL) ) + (-10)) : __builtin_avr_delay_cycles(0)); } } } while(0); do { for (volatile int8_t __wsba_i = 7; __wsba_i >= 0; --__wsba_i) { if ((((((rgb24_t) (c)) >> 0) & 0xFF)) & (1 << __wsba_i)) { __asm__ __volatile__("":::"memory"); do { ((*(volatile uint8_t *)((0x05) + 0x20))) |= (1 << (uint8_t)((2))); } while(0); (((( (700) / (1000000000L / (signed long) 16000000UL) ) + (-2)) > 0) ? __builtin_avr_delay_cycles(( (700) / (1000000000L / (signed long) 16000000UL) ) + (-2)) : __builtin_avr_delay_cycles(0)); __asm__ __volatile__("":::"memory"); do { ((*(volatile uint8_t *)((0x05) + 0x20))) &= ~(1 << (uint8_t)((2))); } while(0); (((( (150) / (1000000000L / (signed long) 16000000UL) ) + (-10)) > 0) ? __builtin_avr_delay_cycles(( (150) / (1000000000L / (signed long) 16000000UL) ) + (-10)) : __builtin_avr_delay_cycles(0)); } else { __asm__ __volatile__("":::"memory"); do { ((*(volatile uint8_t *)((0x05) + 0x20))) |= (1 << (uint8_t)((2))); } while(0); (((( (150) / (1000000000L / (signed long) 16000000UL) ) + (-2)) > 0) ? __builtin_avr_delay_cycles(( (150) / (1000000000L / (signed long) 16000000UL) ) + (-2)) : __builtin_avr_delay_cycles(0)); __asm__ __volatile__("":::"memory"); do { ((*(volatile uint8_t *)((0x05) + 0x20))) &= ~(1 << (uint8_t)((2))); } while(0); (((( (700) / (1000000000L / (signed long) 16000000UL) ) + (-10)) > 0) ? __builtin_avr_delay_cycles(( (700) / (1000000000L / (signed long) 16000000UL) ) + (-10)) : __builtin_avr_delay_cycles(0)); } } } while(0); } while(0);
}
do { __asm__ __volatile__("":::"memory"); (((( (7000) / (1000000000L / (signed long) 16000000UL) ) + (0)) > 0) ? __builtin_avr_delay_cycles(( (7000) / (1000000000L / (signed long) 16000000UL) ) + (0)) : __builtin_avr_delay_cycles(0)); } while(0);
}

@ -0,0 +1 @@
/home/ondra/devel/avr/avr-projects/devel/lib

@ -18,8 +18,10 @@
#include "lib/debounce.h"
#define BOARD_WIDTH 6
#define BOARD_HEIGHT 5
// #define BOARD_WIDTH 6
// #define BOARD_HEIGHT 5
#define BOARD_WIDTH 4
#define BOARD_HEIGHT 4
// number of cards
#define CARD_COUNT (BOARD_WIDTH * BOARD_HEIGHT)
@ -30,20 +32,20 @@
// color palette
const xrgb_t COLORS[] = {
rgb24_xrgbc(0x00FF99), // emerald
rgb24_xrgbc(0x00CCCC), // cyan
rgb24_xrgbc(0x0000CC), // full blue
rgb24_xrgbc(0xFF6D55), // salmon?
rgb24_xrgbc(0x4400FF), // blue-purple
rgb24_xrgbc(0xFF00FF), // magenta
rgb24_xrgbc(0xD70053), // wine
rgb24_xrgbc(0xFF0000), // red
rgb24_xrgbc(0xCD2B64), // brick
rgb24_xrgbc(0xED1B24), // firetruck red
rgb24_xrgbc(0xFF6D00), // tangerine yellow/orange
rgb24_xrgbc(0xFF2B00), // orange
rgb24_xrgbc(0xFFFF00), // yellow
rgb24_xrgbc(0x5FBA00), // yellow-green
rgb24_xrgbc(0x0BEE00), // green
rgb24_xrgbc(0xFF6D00), // tangerine yellow/orange
rgb24_xrgbc(0x00CCCC), // cyan
rgb24_xrgbc(0x4400FF), // blue-purple
rgb24_xrgbc(0x5FBA00), // yellow-green
rgb24_xrgbc(0xD70053), // wine
rgb24_xrgbc(0xCD2B64), // brick
rgb24_xrgbc(0xED1B24), // firetruck red
rgb24_xrgbc(0xFF6D55), // salmon?
};

@ -0,0 +1,166 @@
MCU = atmega328p
F_CPU = 16000000
LFUSE = 0xFF
HFUSE = 0xDE
EFUSE = 0x05
MAIN = main.c
## If you've split your program into multiple files,
## include the additional .c source (in same directory) here
## (and include the .h files in your foo.c)
LOCAL_SOURCE =
## Here you can link to one more directory (and multiple .c files)
# EXTRA_SOURCE_DIR = ../AVR-Programming-Library/
EXTRA_SOURCE_DIR =
EXTRA_SOURCE_FILES =
##########------------------------------------------------------##########
########## Programmer Defaults ##########
########## Set up once, then forget about it ##########
########## (Can override. See bottom of file.) ##########
##########------------------------------------------------------##########
#19200
PROGRAMMER_TYPE = arduino
PROGRAMMER_ARGS = -b 57600 -P /dev/ttyUSB0
##########------------------------------------------------------##########
########## Makefile Magic! ##########
########## Summary: ##########
########## We want a .hex file ##########
########## Compile source files into .elf ##########
########## Convert .elf file into .hex ##########
########## You shouldn't need to edit below. ##########
##########------------------------------------------------------##########
## Defined programs / locations
CC = avr-gcc
OBJCOPY = avr-objcopy
OBJDUMP = avr-objdump
AVRSIZE = avr-size
AVRDUDE = sudo avrdude
## Compilation options, type man avr-gcc if you're curious.
CFLAGS = -std=gnu99 -mmcu=$(MCU) -DF_CPU=$(F_CPU)UL -I. -I$(EXTRA_SOURCE_DIR)
CFLAGS += -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums
CFLAGS += -Wall -Wno-main -Wno-strict-prototypes -Wno-comment
CFLAGS += -g2 -Wextra -pedantic -Wfatal-errors
CFLAGS += -ffunction-sections -fdata-sections -Wl,--gc-sections -Wl,--relax
CFLAGS_BUILD = $(CFLAGS) -Os
# CFLAGS += -lm
## CFLAGS += -Wl,-u,vfprintf -lprintf_flt -lm ## for floating-point printf
## CFLAGS += -Wl,-u,vfprintf -lprintf_min ## for smaller printf
## Lump target and extra source files together
TARGET = $(strip $(basename $(MAIN)))
SRC1 = $(TARGET).c
SRC = $(SRC1)
EXTRA_SOURCE = $(addprefix $(EXTRA_SOURCE_DIR), $(EXTRA_SOURCE_FILES))
SRC += $(EXTRA_SOURCE)
SRC += $(LOCAL_SOURCE)
## List of all header files
HEADERS = $(SRC:.c=.h)
## For every .c file, compile an .o object file
OBJ = $(SRC:.c=.o)
## Generic Makefile targets. (Only .hex file is necessary)
all: $(TARGET).hex size
pre: $(TARGET).pre
%.hex: %.elf
$(OBJCOPY) -R .eeprom -O ihex $< $@
%.elf: $(SRC)
$(CC) $(CFLAGS_BUILD) $(SRC) --output $@
%.pre: $(SRC1)
$(CC) $(CFLAGS) -E $(SRC1) --output $@
%.eeprom: %.elf
$(OBJCOPY) -j .eeprom --change-section-lma .eeprom=0 -O ihex $< $@
debug:
@echo
@echo "Source files:" $(SRC)
@echo "MCU, F_CPU, BAUD:" $(MCU), $(F_CPU), $(BAUD)
@echo
# Optionally create listing file from .elf
# This creates approximate assembly-language equivalent of your code.
# Useful for debugging time-sensitive bits,
# or making sure the compiler does what you want.
disassemble: $(TARGET).lst
dis: disassemble
lst: disassemble
eeprom: $(TARGET).eeprom
%.lst: %.elf
$(OBJDUMP) -S $< > $@
# Optionally show how big the resulting program is
size: $(TARGET).elf
$(AVRSIZE) -C --mcu=$(MCU) $(TARGET).elf
clean:
rm -f $(TARGET).elf $(TARGET).hex $(TARGET).obj \
$(TARGET).o $(TARGET).d $(TARGET).eep $(TARGET).lst \
$(TARGET).lss $(TARGET).sym $(TARGET).map $(TARGET)~ \
$(TARGET).eeprom
squeaky_clean:
rm -f *.elf *.hex *.obj *.o *.d *.eep *.lst *.lss *.sym *.map *~
##########------------------------------------------------------##########
########## Programmer-specific details ##########
########## Flashing code to AVR using avrdude ##########
##########------------------------------------------------------##########
flash: $(TARGET).hex
$(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) $(PROGRAMMER_ARGS) -U flash:w:$<
flash_eeprom: $(TARGET).eeprom
$(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) $(PROGRAMMER_ARGS) -U eeprom:w:$<
terminal:
$(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) $(PROGRAMMER_ARGS) -nt
flash_arduino: PROGRAMMER_TYPE = arduino
flash_arduino: PROGRAMMER_ARGS =
flash_arduino: flash
flash_dragon_isp: PROGRAMMER_TYPE = dragon_isp
flash_dragon_isp: PROGRAMMER_ARGS =
flash_dragon_isp: flash
##########------------------------------------------------------##########
########## Fuse settings and suitable defaults ##########
##########------------------------------------------------------##########
## Generic
FUSE_STRING = -U lfuse:w:$(LFUSE):m -U hfuse:w:$(HFUSE):m -U efuse:w:$(EFUSE):m
fuses:
$(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) \
$(PROGRAMMER_ARGS) $(FUSE_STRING)
show_fuses:
$(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) $(PROGRAMMER_ARGS) -nv
## Called with no extra definitions, sets to defaults
set_default_fuses: FUSE_STRING = -U lfuse:w:$(LFUSE):m -U hfuse:w:$(HFUSE):m -U efuse:w:$(EFUSE):m
set_default_fuses: fuses

@ -0,0 +1,31 @@
Color Memory Game
=================
This is a memory game (with pairs of cards), played on a WS2812B RGB LED strip.
The code is designed for *Arduino Pro Mini* (16 MHz), and can be flashed with avrdude (use the Makefile) using a USB-to-serial adapter.
Peripherals
-----------
- WS2812B RGB LED strip (or chained pixels) for the game board
- 4 buttons for navigation (arrows)
- 2 buttons for RESTART and SELECT
The LED strip should have a large capacitor (~ 1000uF) in parallel to the power supply, to avoid flickering.
It's connected over a resistor (470R will do fine) to the Arduino.
All pins can be adjusted in the `main.c` near the top, also the board size can be changed (for more than 15 card pairs, you'll have to add more colors).
Board
-----
The LEDs are numbered in this manner:
0 1 2 3
4 5 6 7
8 9 10 11
12 13 14 15
Set the board width and height in `main.c` to match your setup.

@ -0,0 +1,6 @@
MightyPorsk's AVR utils library
===============================
This is my ever-evolving library. When I'm done with a project, I copy the current library to the project, so it doesn't break when I do further improvements.
Each library file contains a large comment block explaining it's function.

@ -0,0 +1,39 @@
#pragma once
#include <avr/io.h>
#include <stdbool.h>
#include "calc.h"
/** Initialize the ADC */
void adc_init()
{
ADCSRA |= _BV(ADPS2) | _BV(ADPS1) | _BV(ADPS0); // 128 prescaler -> 125 kHz
ADMUX |= _BV(REFS0); // Voltage reference
sbi(ADCSRA, ADEN); // Enable ADC
}
/** Sample analog pin with 8-bit precision */
uint8_t adc_read_byte(uint8_t channel)
{
write_low_nibble(ADMUX, channel); // Select channel to sample
sbi(ADMUX, ADLAR); // Align result to left
sbi(ADCSRA, ADSC); // Start conversion
while(bit_is_high(ADCSRA, ADSC)); // Wait for it...
return ADCH; // The upper 8 bits of ADC result
}
/** Sample analog pin with 10-bit precision */
uint16_t adc_read_word(uint8_t channel)
{
write_low_nibble(ADMUX, channel); // Select channel to sample
cbi(ADMUX, ADLAR); // Align result to right
sbi(ADCSRA, ADSC); // Start conversion
while(get_bit(ADCSRA, ADSC)); // Wait for it...
return ADCW; // The whole ADC word (10 bits)
}

@ -0,0 +1,42 @@
#pragma once
/**
Pin definitions for Arduino (Pro Mini with ATmega328P)
*/
#include "pins.h"
#define D0 D,0
#define D1 D,1
#define D2 D,2
#define D3 D,3
#define D4 D,4
#define D5 D,5
#define D6 D,6
#define D7 D,7
#define D8 B,0
#define D9 B,1
#define D10 B,2
// MOSI MISO SCK - not good for input
#define D11 B,3
#define D12 B,4
#define D13 B,5
#define D14 C,0
#define D15 C,1
#define D16 C,2
#define D17 C,3
#define D18 C,4
#define D19 C,5
#define D20 C,6
#define D21 C,7
#define A0 C,0
#define A1 C,1
#define A2 C,2
#define A3 C,3
#define A4 C,4
#define A5 C,5
#define A6 C,6
#define A7 C,7

@ -0,0 +1,46 @@
#pragma once
/**
General purpose calculation and bit manipulation utilities.
*/
// if max, go to zero. Else increment.
#define inc_wrap(var, min, max) do { if ((var) >= (max)) { (var)=min; } else { (var)++; } } while(0)
// If zero, go to max. Else decrement,
#define dec_wrap(var, min, max) do { if ((var) > min) { (var)--; } else { (var)=(max); } } while(0)
// === general bit manipulation with register ===
#define sbi(reg, bit) do { (reg) |= (1 << (uint8_t)(bit)); } while(0)
#define cbi(reg, bit) do { (reg) &= ~(1 << (uint8_t)(bit)); } while(0)
#define read_bit(reg, bit) ((((uint8_t)(reg)) >> (uint8_t)(bit)) & 0x1)
#define get_bit(reg, bit) read_bit(reg, bit)
#define bit_is_high(reg, bit) read_bit(reg, bit)
#define bit_is_low(reg, bit) !read_bit(reg, bit)
// Can't use bit_is_set, as it's redefined in sfr_def.h
#define write_bit(reg, bit, value) do { (reg) = ((reg) & ~(1 << (uint8_t)(bit))) | (((uint8_t)(value) & 0x1) << (uint8_t)(bit)); } while(0)
#define set_bit(reg, bit, value) write_bit(reg, bit, value)
#define toggle_bit(reg, bit) do { (reg) ^= (1 << (uint8_t)(bit)); } while(0)
// general pin manipulation - with pointer to register
#define sbi_p(reg_p, bit) do { (*(reg_p)) |= (1 << (uint8_t)(bit)); } while(0)
#define cbi_p(reg_p, bit) do { (*(reg_p)) &= ~(1 << (uint8_t)(bit)); } while(0)
#define read_bit_p(reg_p, bit) ((*(reg_p) >> (uint8_t)(bit)) & 0x1)
#define get_bit_p(reg_p, bit) read_bit_p(reg_p, bit)
#define write_bit_p(reg_p, bit, value) do { *(reg_p) = (*(reg_p) & ~(1 << ((uint8_t)(bit) & 0x1))) | (((uint8_t)(value) & 0x1) << (uint8_t)(bit)); } while(0)
#define set_bit_p(reg, bit, value) write_bit_p(reg_p, bit, value)
#define toggle_bit_p(reg_p, bit) do { *(reg_p) ^= (1 << (uint8_t)(bit)); } while(0)
#define write_low_nibble(reg, value) do { (reg) = ((reg) & 0xF0) | ((uint8_t)(value) & 0xF); } while(0)
#define write_high_nibble(reg, value) do { (reg) = ((reg) & 0x0F) | (((uint8_t)(value) & 0xF) << 4); } while(0)
// Check if value is in range A..B or B..A
#define in_range(x, low, high) (((low) < (high)) && ((x) > (low) && (x) < (high))) || (((low) > (high)) && ((x) < (low) || (x) > (high)))
// Check if value is in range A..B. If B < A, matches all outside B..A
#define in_range_wrap(x, low, high) (((low) < (high)) && ((x) > (low) && (x) < (high))) || (((low) > (high)) && ((x) > (low) || (x) < (high)))

@ -0,0 +1,83 @@
#pragma once
/*
Some useful utilities for RGB color manipulation
The XXXc macros don't use cast, so they can be used in array initializers.
xrgb ... 3-byte true-color RGB (8 bits per component)
rgbXX ... XX-bit color value, with equal nr of bits per component
XX_r (_g, _b) ... extract component from the color, and convert it to 0..255
*/
typedef struct {
uint8_t r;
uint8_t g;
uint8_t b;
} xrgb_t;
typedef uint32_t rgb24_t;
typedef uint16_t rgb16_t;
typedef uint16_t rgb12_t;
typedef uint8_t rgb6_t;
#define xrgb(rr, gg, bb) ((xrgb_t)xrgbc(rr, gg, bb))
// xrgb for constant array declarations
#define xrgbc(rr, gg, bb) { .r = ((uint8_t)(rr)), .g = ((uint8_t)(gg)), .b = ((uint8_t)(bb)) }
#define xrgb_r(c) ((uint8_t)(c.r))
#define xrgb_g(c) ((uint8_t)(c.g))
#define xrgb_b(c) ((uint8_t)(c.b))
#define xrgb_rgb24(c) ((((rgb24_t)c.r) << 16) | (((rgb24_t)c.g) << 8) | (((rgb24_t)c.b)))
#define xrgb_rgb15(c) (((((rgb15_t)c.r) & 0xF8) << 7) | ((((rgb15_t)c.g) & 0xF8) << 2) | ((((rgb15_t)c.b) & 0xF8) >> 3))
#define xrgb_rgb12(c) (((((rgb12_t)c.r) & 0xF0) << 4) | ((((rgb12_t)c.g) & 0xF0)) | ((((rgb12_t)c.b) & 0xF0) >> 4))
#define xrgb_rgb6(c) (((((rgb6_t)c.r) & 0xC0) >> 2) | ((((rgb6_t)c.g) & 0xC0) >> 4) | ((((rgb6_t)c.b) & 0xC0) >> 6))
#define rgb24c(r,g,b) (((((rgb24_t)r) & 0xFF) << 16) | ((((rgb24_t)g) & 0xFF) << 8) | (((rgb24_t)b) & 0xFF))
#define rgb24(r,g,b) ((rgb24_t) rgb24(r,g,b))
#define rgb24_r(c) ((((rgb24_t) (c)) >> 16) & 0xFF)
#define rgb24_g(c) ((((rgb24_t) (c)) >> 8) & 0xFF)
#define rgb24_b(c) ((((rgb24_t) (c)) >> 0) & 0xFF)
#define rgb24_xrgb(c) xrgb(rgb24_r(c), rgb24_g(c), rgb24_b(c))
#define rgb24_xrgbc(c) xrgbc(rgb24_r(c), rgb24_g(c), rgb24_b(c))
#define rgb15(r,g,b) ((rgb16_t) rgb15c(r,g,b))
#define rgb15c(r,g,b) (((r & 0x1F) << 10) | ((g & 0x1F) << 5) | (b & 0x1F))
#define rgb15_r(c) ((((rgb15_t) (c)) & 0x7C00) >> 7)
#define rgb15_g(c) ((((rgb15_t) (c)) & 0x3E0) >> 2)
#define rgb15_b(c) ((((rgb15_t) (c)) & 0x1F) << 3)
#define rgb15_xrgb(c) xrgb(rgb15_r(c), rgb15_g(c), rgb15_b(c))
#define rgb15_rgb24(c) rgb24(rgb15_r(c), rgb15_g(c), rgb15_b(c))
#define rgb15_rgb24c(c) rgb24c(rgb15_r(c), rgb15_g(c), rgb15_b(c))
#define rgb12(r,g,b) ((rgb12_t) rgb12c(r,g,b))
#define rgb12c(r,g,b) (((r & 0xF) << 8) | ((g & 0xF) << 4) | (b & 0xF))
#define rgb12_r(c) ((((rgb12_t) (c)) & 0xF00) >> 4)
#define rgb12_g(c) (((rgb12_t) (c)) & 0xF0)
#define rgb12_b(c) (((r(rgb12_t) (c)gb) & 0x0F) << 4)
#define rgb12_xrgb(c) xrgb(rgb12_r(c), rgb12_g(c), rgb12_b(c))
#define rgb12_xrgbc(c) xrgbc(rgb12_r(c), rgb12_g(c), rgb12_b(c))
#define rgb12_rgb24(c) rgb24(rgb12_r(c), rgb12_g(c), rgb12_b(c))
#define rgb12_rgb24c(c) rgb24c(rgb12_r(c), rgb12_g(c), rgb12_b(c))
#define rgb6(r,g,b) ((rgb6_t) rgb6c(r,g,b))
#define rgb6c(r,g,b) (((r & 3) << 4) | ((g & 3) << 2) | (b & 3))
#define rgb6_r(c) ((((rgb6_t) (c)) & 0x30) << 2)
#define rgb6_g(c) ((((rgb6_t) (c)) & 0xC) << 4)
#define rgb6_b(c) ((((rgb6_t) (c)) & 0x3) << 6)
#define rgb6_xrgb(c) xrgb(rgb6_r(c), rgb6_g(c), rgb6_b(c))
#define rgb6_xrgbc(c) xrgbc(rgb6_r(c), rgb6_g(c), rgb6_b(c))
#define rgb6_rgb24(c) rgb24(rgb6_r(c), rgb6_g(c), rgb6_b(c))
#define rgb6_rgb24c(c) rgb24c(rgb6_r(c), rgb6_g(c), rgb6_b(c))
#define add_xrgb(x, y) ((xrgb_t) { (((y).r > (255 - (x).r)) ? 255 : ((x).r + (y).r)), (((y).g > (255 - (x).g)) ? 255 : ((x).g + (y).g)), (((y).b > 255 - (x).b) ? 255 : ((x).b + (y).b)) })

@ -0,0 +1,104 @@
#pragma once
/**
An implementation of button debouncer.
First, the system must be initialized - even before including:
#define DEBO_CHANNELS 2
#define DEBO_TICKS 5
#inclue "lib/debounce.h"
A pin is registered like this:
#define BTN1 B,0
#define BTN2 B,1
debo_add(BTN0); // The function returns number assigned to the pin (0, 1, ...)
debo_add_rev(BTN1); // active low
debo_register(&PINB, PB2, 0); // direct access - register, pin & invert
Then periodically call the tick function (perhaps in a timer interrupt):
debo_tick();
To check if input is active, use
debo_get_pin(0); // state of input registered as #0
debo_get_pin(1); // state of input registered as #1
*/
#include <avr/io.h>
#include <stdbool.h>
#include "calc.h"
#include "pins.h"
// Number of pins to debounce
#ifndef DEBO_CHANNELS
# error "DEBO_CHANNELS not defined!"
#endif
#ifndef DEBO_TICKS
# warning "DEBO_TICKS not defined, defaulting to 5!"
# define DEBO_TICKS 5
#endif
/* Internal deboucer entry */
typedef struct {
PORT_P reg;
uint8_t bit;
uint8_t count;
} debo_slot_t;
/** Debounce data array */
debo_slot_t debo_slots[DEBO_CHANNELS];
uint8_t debo_next_slot = 0;
/** Define a debounced pin (must be IO!) */
#define debo_add_rev(io) debo_register(&io2pin(io_pack(io)), io2n(io_pack(io)), 1)
#define debo_add(io) debo_register(&io2pin(io_pack(io)), io2n(io_pack(io)), 0)
uint8_t debo_register(PORT_P reg, uint8_t bit, bool invert)
{
debo_slots[debo_next_slot] = (debo_slot_t){
.reg = reg,
.bit = bit | ((invert & 1) << 7) | (get_bit_p(reg, bit) << 6), // bit 7 = invert, bit 6 = state
.count = 0,
};
return debo_next_slot++;
}
/** Check debounced pins, should be called periodically. */
void debo_tick()
{
for (uint8_t i = 0; i < debo_next_slot; i++) {
// current pin value (right 3 bits, xored with inverse bit)
bool value = get_bit_p(debo_slots[i].reg, debo_slots[i].bit & 0x7);
if (value != get_bit(debo_slots[i].bit, 6)) {
// different pin state than last recorded state
if (debo_slots[i].count < DEBO_TICKS) {
debo_slots[i].count++;
} else {
// overflown -> latch value
set_bit(debo_slots[i].bit, 6, value); // set state bit
debo_slots[i].count = 0;
}
} else {
debo_slots[i].count = 0; // reset the counter
}
}
}
/** Get a value of debounced pin */
#define debo_get_pin(i) (get_bit(debo_slots[i].bit, 6) ^ get_bit(debo_slots[i].bit, 7))
//(get_bit(debo_slots[i].bit, 6) ^ get_bit(debo_slots[i].bit, 7))

@ -0,0 +1,6 @@
#pragma once
/** Weird constructs for the compiler */
// general macros
#define SECTION(pos) __attribute__((naked, used, section(pos)))

@ -0,0 +1,18 @@
#pragma once
/**
Functions for precise delays (nanoseconds / cycles)
*/
#include <avr/io.h>
#include <util/delay_basic.h>
#include <stdint.h>
/* Convert nanoseconds to cycle count */
#define ns2cycles(ns) ( (ns) / (1000000000L / (signed long) F_CPU) )
/** Wait c cycles */
#define delay_c(c) (((c) > 0) ? __builtin_avr_delay_cycles(c) : __builtin_avr_delay_cycles(0))
/** Wait n nanoseconds, plus c cycles */
#define delay_ns_c(ns, c) delay_c(ns2cycles(ns) + (c))

@ -0,0 +1,107 @@
#pragma once
/**
This file provides macros for pin manipulation.
You can define your application pins like so:
// Led at PORTB, pin 1
#define LED B,1
// Switch at PORTD, pin 7
#define SW1 D,7
Now you can use macros from this file to wirh with the pins, eg:
as_output(LED);
as_input(SW1);
pullup_on(SW1);
toggle_pin(LED);
while (pin_is_low(SW1));
- The macros io2XXX() can be used to get literal name of register associated with the pin.
- io2n() provides pin number.
- The XXX_aux() macros are internal and should not be used elsewhere.
- The io_pack() macro is used to pass pin (io) to other macro without expanding it.
*/
#include <avr/io.h>
#include "calc.h"
// Get particular register associated with the name X (eg. D -> PORTD)
#define reg_ddr(X) DDR ## X
#define reg_port(X) PORT ## X
#define reg_pin(X) PIN ## X
#define io2ddr_aux(reg, bit) reg_ddr(reg)
#define io2ddr(io) io2ddr_aux(io)
#define io2port_aux(reg, bit) reg_port(reg)
#define io2port(io) io2port_aux(io)
#define io2pin_aux(reg, bit) reg_pin(reg)
#define io2pin(io) io2pin_aux(io)
#define io2n_aux(reg, bit) bit
#define io2n(io) io2n_aux(io)
#define io_pack(port, bit) port, bit
// pointer to port
typedef volatile uint8_t* PORT_P;
// number of bit in port
typedef uint8_t BIT_N;
// === pin manipulation ===
#define set_pin_aux(port, bit) sbi(reg_port(port), (bit))
#define clear_pin_aux(port, bit) cbi(reg_port(port), (bit))
#define read_pin_aux(port, bit) get_bit(reg_pin(port), (bit))
#define write_pin_aux(port, bit, value) set_bit(reg_port(port), (bit), (value))
#define toggle_pin_aux(port, bit) sbi(reg_pin(port), (bit))
#define pin_up(io) set_pin_aux(io)
#define pin_high(io) set_pin_aux(io)
#define pin_down(io) clear_pin_aux(io)
#define pin_low(io) clear_pin_aux(io)
#define get_pin(io) read_pin_aux(io)
#define read_pin(io) read_pin_aux(io)
#define pin_is_low(io) !read_pin_aux(io)
#define pin_is_high(io) read_pin_aux(io)
#define set_pin(io, value) write_pin_aux(io, (value))
#define write_pin(io, value) write_pin_aux(io, (value))
#define toggle_pin(io) toggle_pin_aux(io)
// setting pin direction
#define as_input_aux(port, bit) cbi(reg_ddr(port), (bit))
#define as_output_aux(port, bit) sbi(reg_ddr(port), (bit))
#define set_dir_aux(port, bit, dir) write_bit(reg_ddr(port), (bit), (dir))
#define as_input(io) as_input_aux(io)
#define as_input_pu(io) do { as_input_aux(io); pullup_enable_aux(io); } while(0)
#define as_output(io) as_output_aux(io)
#define set_dir(io, dir) set_dir_aux(io, (dir))
// setting pullup
#define pullup_enable_aux(port, bit) sbi(reg_port(port), (bit))
#define pullup_disable_aux(port, bit) cbi(reg_port(port), (bit))
#define set_pullup_aux(port, bit, on) write_bit(reg_port(port), (bit), (on))
#define pullup_enable(io) pullup_enable_aux(io)
#define pullup_on(io) pullup_enable_aux(io)
#define pullup_disable(io) pullup_disable_aux(io)
#define pullup_off(io) pullup_disable_aux(io)
#define set_pullup(io, on) set_pullup_aux(io, on)

@ -0,0 +1,98 @@
#pragma once
/**
Utils for driving a WS2812 (WS2812B) RGB LED strips.
It's implemented as macros to avoid overhead when passing values, and to
enable driving multiple strips at once.
To avoid bloating your code, try to reduce the number of invocations -
compute color and then send it.
[IMPORTANT]
Some seemingly random influences can ruin the communication.
If you have enough memory, consider preparing the colors in array,
and sending this array using one of the "ws_send_XXX_array" macros.
*/
#include <avr/io.h>
#include "pins.h"
#include "nsdelay.h"
#include "colors.h"
/* Driver code for WS2812B */
// --- timing constraints (NS) ---
#ifndef WS_T_1H
# define WS_T_1H 700
#endif
#ifndef WS_T_1L
# define WS_T_1L 150
#endif
#ifndef WS_T_0H
# define WS_T_0H 150
#endif
#ifndef WS_T_0L
# define WS_T_0L 700
#endif
#ifndef WS_T_LATCH
# define WS_T_LATCH 7000
#endif
/** Wait long enough for the colors to show */
#define ws_show() do {delay_ns_c(WS_T_LATCH, 0); } while(0)
/** Send one byte to the RGB strip */
#define ws_send_byte(io, bb) do { \
for (volatile int8_t __ws_tmp = 7; __ws_tmp >= 0; --__ws_tmp) { \
if ((bb) & (1 << __ws_tmp)) { \
pin_high(io_pack(io)); delay_ns_c(WS_T_1H, -2); \
pin_low(io_pack(io)); delay_ns_c(WS_T_1L, -10); \
} else { \
pin_high(io_pack(io)); delay_ns_c(WS_T_0H, -2); \
pin_low(io_pack(io)); delay_ns_c(WS_T_0L, -10); \
} \
} \
} while(0)
/** Send R,G,B color to the strip */
#define ws_send_rgb(io, r, g, b) do { \
ws_send_byte(io_pack(io), g); \
ws_send_byte(io_pack(io), r); \
ws_send_byte(io_pack(io), b); \
} while(0)
/** Send a RGB struct */
#define ws_send_xrgb(io, xrgb) ws_send_rgb(io_pack(io), (xrgb).r, (xrgb).g, (xrgb).b)
/** Send color hex */
#define ws_send_rgb24(io, rgb) ws_send_rgb(io_pack(io), rgb24_r(rgb), rgb24_g(rgb), rgb24_b(rgb))
#define ws_send_rgb15(io, rgb) ws_send_rgb(io_pack(io), rgb15_r(rgb), rgb15_g(rgb), rgb15_b(rgb))
#define ws_send_rgb12(io, rgb) ws_send_rgb(io_pack(io), rgb12_r(rgb), rgb12_g(rgb), rgb12_b(rgb))
#define ws_send_rgb6(io, rgb) ws_send_rgb(io_pack(io), rgb6_r(rgb), rgb6_g(rgb), rgb6_b(rgb))
/** Send array of colors */
#define ws_send_xrgb_array(io, rgbs, length) __ws_send_array_proto(io_pack(io), (rgbs), (length), xrgb)
#define ws_send_rgb24_array(io, rgbs, length) __ws_send_array_proto(io_pack(io), (rgbs), (length), rgb24)
#define ws_send_rgb15_array(io, rgbs, length) __ws_send_array_proto(io_pack(io), (rgbs), (length), rgb15)
#define ws_send_rgb12_array(io, rgbs, length) __ws_send_array_proto(io_pack(io), (rgbs), (length), rgb12)
#define ws_send_rgb6_array(io, rgbs, length) __ws_send_array_proto(io_pack(io), (rgbs), (length), rgb6)
// prototype for sending array. it's ugly, sorry.
#define __ws_send_array_proto(io, rgbs, length, style) do { \
for (uint8_t __ws_tmp_sap_i = 0; __ws_tmp_sap_i < length; __ws_tmp_sap_i++) { \
style ## _t __ws_tmp_sap2 = (rgbs)[__ws_tmp_sap_i]; \
ws_send_ ## style(io_pack(io), __ws_tmp_sap2); \
} \
} while(0)

@ -0,0 +1,403 @@
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
// #include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
#include "lib/meta.h"
#include "lib/arduino_pins.h"
#include "lib/calc.h"
#include "lib/colors.h"
#include "lib/ws2812.h"
#include "lib/adc.h"
#define DEBO_CHANNELS 6
#define DEBO_TICKS 1 // in 0.01s
#include "lib/debounce.h"
// #define BOARD_WIDTH 6
// #define BOARD_HEIGHT 5
#define BOARD_WIDTH 4
#define BOARD_HEIGHT 4
// number of cards
#define CARD_COUNT (BOARD_WIDTH * BOARD_HEIGHT)
// number of pairs
#define PAIR_COUNT (CARD_COUNT / 2)
// color palette
const xrgb_t COLORS[] = {
rgb24_xrgbc(0x00FF99), // emerald
rgb24_xrgbc(0x0000CC), // full blue
rgb24_xrgbc(0xFF00FF), // magenta
rgb24_xrgbc(0xFF0000), // red
rgb24_xrgbc(0xFF2B00), // orange
rgb24_xrgbc(0xFFFF00), // yellow
rgb24_xrgbc(0x0BEE00), // green
rgb24_xrgbc(0xFF6D00), // tangerine yellow/orange
rgb24_xrgbc(0x00CCCC), // cyan
rgb24_xrgbc(0x4400FF), // blue-purple
rgb24_xrgbc(0x5FBA00), // yellow-green
rgb24_xrgbc(0xD70053), // wine
rgb24_xrgbc(0xCD2B64), // brick
rgb24_xrgbc(0xED1B24), // firetruck red
rgb24_xrgbc(0xFF6D55), // salmon?
};
// assert valid board size
#if CARD_COUNT % 2 == 1
# error "Board size is not even!"
#endif
// Pin assignments (see pins.h)
// RGB LED strip data line
#define WS1 D10
// Buttons (to ground)
#define BTN_LEFT D2
#define BTN_RIGHT D3
#define BTN_UP D4
#define BTN_DOWN D5
#define BTN_SELECT D6
#define BTN_RESTART D7
// Debouncer channels for buttons
// (Must be added in this order to debouncer)
#define D_LEFT 0
#define D_RIGHT 1
#define D_UP 2
#define D_DOWN 3
#define D_SELECT 4
#define D_RESTART 5
// [ IMPORTANT ]
// Pin A0 must not be connected, it is used to get
// entropy for the random number generator
// Prototypes
void render();
void update();
void deal_cards();
/** Program initialization */
void SECTION(".init8") init()
{
// Randomize RNG
adc_init();
srand(adc_read_word(0));
// led strip data
as_output(WS1);
// gamepad buttons
as_input_pu(BTN_LEFT);
as_input_pu(BTN_RIGHT);
as_input_pu(BTN_UP);
as_input_pu(BTN_DOWN);
as_input_pu(BTN_SELECT);
as_input_pu(BTN_RESTART);
// add buttons to debouncer
debo_add_rev(BTN_LEFT);
debo_add_rev(BTN_RIGHT);
debo_add_rev(BTN_UP);
debo_add_rev(BTN_DOWN);
debo_add_rev(BTN_SELECT);
debo_add_rev(BTN_RESTART);
// setup timer
TCCR0A = _BV(WGM01); // CTC
TCCR0B = _BV(CS02) | _BV(CS00); // prescaler 1024
OCR0A = 156; // interrupt every 10 ms
sbi(TIMSK0, OCIE0A);
// prepare game board
deal_cards();
// enable timer interrupts (update & render)
sei();
}
/** Tile state enum */
typedef enum {
SECRET,
REVEALED,
GONE
} tilestate_t;
/** Tile struct */
typedef struct {
uint8_t color; // color index from COLORS[]
tilestate_t state; // state of the tile (used for render)
} tile_t;
// board tiles
tile_t board[CARD_COUNT];
/** Randomly place pairs of cards on the board */
void deal_cards()
{
// clear the board
for (uint8_t i = 0; i < CARD_COUNT; ++i) {
board[i] = (tile_t) { .color = 0, .state = GONE };
}
// for all pair_COUNT
for (uint8_t i = 0; i < PAIR_COUNT; ++i) {
// for both cards in pair
for (uint8_t j = 0; j < 2; j++) {
// loop until empty slot is found
while(1) {
uint8_t pos = rand() % CARD_COUNT;
if (board[pos].state == GONE) {
board[pos] = (tile_t) { .color = i, .state = SECRET };
break;
}
}
}
}
}
/** timer 0 interrupt vector */
ISR(TIMER0_COMPA_vect)
{
debo_tick(); // poll debouncer
update(); // update game state
render();
}
// player cursor position
uint8_t cursor = 0;
uint8_t animframe = 0;
bool hide_timeout_match;
uint8_t hide_timeout = 0;
// Game state
uint8_t tiles_revealed = 0;
uint8_t tile1;
uint8_t tile2;
// length of pulse animation (in 10ms)
#define F_ANIM_LEN 20
#define HIDE_TIME 100
// length of button holding before it's repeated (in 10ms)
#define BTNHOLD_REPEAT 20
uint8_t btn_hold_cnt[DEBO_CHANNELS];
/** Handle a button press event */
void button_click(uint8_t n)
{
switch (n) {
case D_UP:
if (cursor < BOARD_WIDTH) // first row
cursor += (CARD_COUNT - BOARD_WIDTH);
else
cursor -= BOARD_WIDTH;
break;
case D_DOWN:
if (cursor >= (CARD_COUNT - BOARD_WIDTH)) // last row
cursor -= (CARD_COUNT - BOARD_WIDTH);
else
cursor += BOARD_WIDTH;
break;
case D_LEFT:
if (cursor > 0) // last row
cursor--;
else
cursor = (CARD_COUNT - 1);
break;
case D_RIGHT:
if (cursor < (CARD_COUNT - 1)) // last row
cursor++;
else
cursor = 0;
break;
case D_SELECT:
if (tiles_revealed == 2) break; // two already shown
if (board[cursor].state != SECRET) break; // selected tile not secret
// reveal a tile
if (tiles_revealed < 2) {
board[cursor].state = REVEALED;
tiles_revealed++;
if(tiles_revealed == 1) {
tile1 = cursor;
} else {
tile2 = cursor;
}
}
// Check equality if it's the second
if (tiles_revealed == 2) {
hide_timeout_match = (board[tile1].color == board[tile2].color);
hide_timeout = HIDE_TIME;
}
break;
case D_RESTART:
deal_cards();
break;
}
}
/** Press arrow key, skip empty tiles */
void safe_press_arrow_key(uint8_t n)
{
// attempt to arrive at some secret tile
for (uint8_t j = 0; j < BOARD_HEIGHT; j++) {
for (uint8_t k = 0; k < BOARD_WIDTH; k++) {
button_click(n);
if (board[cursor].state != GONE) break;
}
if (board[cursor].state != GONE) break;
// traverse right since current column is empty
//
button_click(D_RIGHT);
}
}
#define is_arrow_key(id) ((id) == D_LEFT || (id) == D_RIGHT || (id) == D_UP || (id) == D_DOWN)
/** Update game (every 10 ms) */
void update()
{
// handle buttons (with repeating when held down)
for (uint8_t i = 0; i < DEBO_CHANNELS; i++) {
if (debo_get_pin(i)) {
if (btn_hold_cnt[i] == 0) {
if (is_arrow_key(i)) {
safe_press_arrow_key(i);
} else {
button_click(i);
}
}
// non-arrows wrap to 1 -> do not generate repeated clicks
inc_wrap(btn_hold_cnt[i], is_arrow_key(i) ? 1 : 0, BTNHOLD_REPEAT);
} else {
btn_hold_cnt[i] = 0;
}
}
// game logic - hide or remove cards when time is up
if (hide_timeout > 0) {
if (--hide_timeout == 0) {
if (hide_timeout_match) {
// Tiles removed from board
board[tile1].state = GONE;
board[tile2].state = GONE;
if (board[cursor].state == GONE) {
// move to some other tile
// try not to change row if possible
if ((cursor % BOARD_WIDTH) == (BOARD_WIDTH-1))
safe_press_arrow_key(D_LEFT);
else
safe_press_arrow_key(D_RIGHT);
}
} else {
// Tiles made secret again
board[tile1].state = SECRET;
board[tile2].state = SECRET;
}
tiles_revealed = 0; // no revealed
}
}
// Animation for pulsing the active color
inc_wrap(animframe, 0, F_ANIM_LEN * 2);
}
// LED off
#define BLACK rgb24_xrgb(0x000000)
// LED on - secret tile
#define WHITE rgb24_xrgb(0x555555)
// colors to be displayed
xrgb_t screen[CARD_COUNT];
/** Update screen[] and send to display */
void render()
{
// Prepare screen (compute colors)
for (uint8_t i = 0; i < CARD_COUNT; i++) {
// get tile color to show
switch (board[i].state) {
case SECRET:
screen[i] = WHITE;
break;
case REVEALED:
screen[i] = COLORS[board[i].color];
break;
default:
case GONE:
screen[i] = BLACK;
break;
}
// pulse active tile
if (i == cursor) {
uint16_t mult;
if (animframe < F_ANIM_LEN) {
mult = animframe;
} else {
mult = (F_ANIM_LEN * 2) - animframe;
}
screen[i] = (xrgb_t) {
.r = (uint8_t) ((((uint16_t) screen[i].r) * mult) / F_ANIM_LEN),
.g = (uint8_t) ((((uint16_t) screen[i].g) * mult) / F_ANIM_LEN),
.b = (uint8_t) ((((uint16_t) screen[i].b) * mult) / F_ANIM_LEN),
};
}
}
// Send to LEDs
ws_send_xrgb_array(WS1, screen, CARD_COUNT);
ws_show();
}
void main()
{
while(1); // Timer does everything
}
Loading…
Cancel
Save