Skip to content

Commit b1ef3af

Browse files
Merge remote-tracking branch 'upstream/master' into spi_bitbang
2 parents dfc7fbe + cecc6e8 commit b1ef3af

File tree

8 files changed

+786
-13
lines changed

8 files changed

+786
-13
lines changed

examples/board_rotenc/Makefile

+54
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
#
2+
# Copyright 2008-2012 Michel Pollet <[email protected]>
3+
# Copyright 2018 Doug Szumski <[email protected]>
4+
#
5+
# This file is part of simavr.
6+
#
7+
# simavr is free software: you can redistribute it and/or modify
8+
# it under the terms of the GNU General Public License as published by
9+
# the Free Software Foundation, either version 3 of the License, or
10+
# (at your option) any later version.
11+
#
12+
# simavr is distributed in the hope that it will be useful,
13+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+
# GNU General Public License for more details.
16+
#
17+
# You should have received a copy of the GNU General Public License
18+
# along with simavr. If not, see <http://www.gnu.org/licenses/>.
19+
20+
target=rotenc_test
21+
firm_src = ${wildcard at*${board}.c}
22+
firmware = ${firm_src:.c=.axf}
23+
simavr = ../..
24+
25+
IPATH = .
26+
IPATH += ${simavr}/examples/shared
27+
IPATH += ${simavr}/examples/parts
28+
IPATH += ${simavr}/include
29+
IPATH += ${simavr}/simavr/sim
30+
31+
VPATH = .
32+
VPATH += ${simavr}/examples/shared
33+
VPATH += ${simavr}/examples/parts
34+
35+
LDFLAGS += -lpthread
36+
37+
include ../Makefile.opengl
38+
39+
all: obj ${firmware} ${target}
40+
41+
include ${simavr}/Makefile.common
42+
43+
atmega1280_${target}.axf: atmega32_${target}.c
44+
45+
board = ${OBJ}/${target}.elf
46+
47+
${board} : ${OBJ}/${target}.o
48+
${board} : ${OBJ}/rotenc.o
49+
50+
${target}: ${board}
51+
@echo $@ done
52+
53+
clean: clean-${OBJ}
54+
rm -rf *.hex *.a *.axf ${target} *.vcd .*.swo .*.swp .*.swm .*.swn

examples/board_rotenc/README

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
board_rotenc
2+
3+
This sample code demonstrates the use of a virtual Panasonic EVEP rotary
4+
encoder. The encoder is hooked up to an LED array, and is used to scroll
5+
an LED up and down. It behaves just like in real life, except contact
6+
bounce is not modelled.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
/*
2+
atmega32_rotenc_test.c
3+
4+
A simple example demonstrating a Pansonic EVEP rotary encoder
5+
scrolling an LED up and down an 8 segment LED bar.
6+
7+
Copyright 2018 Doug Szumski <[email protected]>
8+
9+
This file is part of simavr.
10+
11+
simavr is free software: you can redistribute it and/or modify
12+
it under the terms of the GNU General Public License as published by
13+
the Free Software Foundation, either version 3 of the License, or
14+
(at your option) any later version.
15+
16+
simavr is distributed in the hope that it will be useful,
17+
but WITHOUT ANY WARRANTY; without even the implied warranty of
18+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19+
GNU General Public License for more details.
20+
21+
You should have received a copy of the GNU General Public License
22+
along with simavr. If not, see <http://www.gnu.org/licenses/>.
23+
*/
24+
25+
#include <avr/io.h>
26+
#include <avr/interrupt.h>
27+
#include <avr/sleep.h>
28+
#include <stdio.h>
29+
30+
#include "avr_mcu_section.h"
31+
AVR_MCU(F_CPU, "atmega32");
32+
33+
typedef enum {
34+
CLOCKWISE,
35+
COUNTERCLOCKWISE
36+
} led_scroll_dir_t;
37+
38+
/* Initialise the inputs for signal A and signal B from the rotary encoder.
39+
* They are hooked up to INTO on PD2 and GPIO pin PA0. Pull-ups are on the
40+
* PCB. */
41+
void
42+
rotary_spin_int_init(void)
43+
{
44+
// Set INT0 and GPIO pin as inputs
45+
DDRD &= ~(1 << PD2) & ~(1 << PA0);
46+
// Any logical change on INT0 generates an interrupt (see DS p.67)
47+
MCUCR |= (1 << ISC00);
48+
MCUCR &= ~(1 << ISC01);
49+
// Enable interrupt pin PD2
50+
GICR |= (1 << INT0);
51+
}
52+
53+
/* Initialise inputs for signal C from the rotary encoder (button). This
54+
* is hooked up to INT2 on PB2. A pull-up is on the PCB. */
55+
void
56+
rotary_button_int_init(void)
57+
{
58+
DDRB &= ~(1 << PB2);
59+
// Falling edge trigger (pin is pulled up) (see DS p.67)
60+
MCUCSR &= ~(1 << ISC2);
61+
// Enable interrupt pin PB2
62+
GICR |= (1 << INT2);
63+
}
64+
65+
/* Configure 8 segment virtual 'LED bar' on port C */
66+
void
67+
led_bar_init(void)
68+
{
69+
DDRC = 0xFF; // All outputs
70+
PORTC = 0b00010000; // Start with a light on in the middle
71+
}
72+
73+
void
74+
led_bar_scroll(led_scroll_dir_t dir)
75+
{
76+
switch (dir) {
77+
case CLOCKWISE:
78+
if (PORTC < 0b10000000) PORTC <<= 1;
79+
break;
80+
case COUNTERCLOCKWISE:
81+
if (PORTC > 0b00000001) PORTC >>= 1;
82+
break;
83+
default:
84+
break;
85+
}
86+
}
87+
88+
int
89+
main()
90+
{
91+
// Disable interrupts whilst configuring them to avoid false triggers
92+
cli();
93+
rotary_spin_int_init();
94+
rotary_button_int_init();
95+
sei();
96+
97+
led_bar_init();
98+
99+
while (1) {
100+
// Wait for some input
101+
}
102+
103+
cli();
104+
sleep_mode();
105+
}
106+
107+
ISR(INT0_vect)
108+
{
109+
// The Panasonic EVEP rotary encoder this is written for moves two
110+
// phases for every 'click' it emits. The interrupt is configured
111+
// to fire on every edge change of B, which is once per 'click'.
112+
// Moving forwards in phase, after B has changed state we poll A.
113+
// We get the sequence (A=0,B=1), (A=1,B=0). Moving backwards in
114+
// phase, after B has changed state we get (A=1,B=1), (A=0,B=0).
115+
//
116+
// +-------+---+---+
117+
// | Phase | A | B |
118+
// +-------+---+---+
119+
// | 0 | 0 | 0 |
120+
// | 1 | 0 | 1 |
121+
// | 2 | 1 | 1 |
122+
// | 3 | 1 | 0 |
123+
// +-------+---+---+
124+
//
125+
// The twist direction is then obtained by taking the logical
126+
// XOR of outputs A and B after the interrupt has fired. Of
127+
// course with a 'real life' part you might be better off
128+
// using a state machine, or some extra hardware to filter out
129+
// contact bounces which aren't modelled in the virtual part.
130+
uint8_t ccw_twist = ((PIND & (1 << PD2)) >> 2) ^ (PINA & (1 << PA0));
131+
132+
// Scroll the LED bar
133+
if (ccw_twist) {
134+
led_bar_scroll(COUNTERCLOCKWISE);
135+
} else {
136+
led_bar_scroll(CLOCKWISE);
137+
}
138+
}
139+
140+
ISR(INT2_vect)
141+
{
142+
// Fires when rotary encoder button was pressed and resets
143+
// the LED bar to the starting position
144+
PORTC = 0b00010000;
145+
}

0 commit comments

Comments
 (0)