https://wiki.koeln.ccc.de/api.php?action=feedcontributions&user=Hendi&feedformat=atom
C4 Wiki - User contributions [en]
2024-03-28T14:52:34Z
User contributions
MediaWiki 1.30.1
https://wiki.koeln.ccc.de/index.php?title=U23_2008-2/Gruppe1&diff=14692
U23 2008-2/Gruppe1
2008-11-17T21:31:56Z
<p>Hendi: /* Eigener Chat (Test) */</p>
<hr />
<div>= Meta Data =<br />
== Mitglieder ==<br />
* Mark<br /><br />
* Christoph<br /><br />
* Hendrik<br /><br />
* Robert<br /><br />
<br />
= Code =<br />
== 1. Abend ==<br />
=== LED - Blinken ===<br />
: Aufgabe: Eine LED soll zum blinken gebracht werden.<br />
: Code:<br />
<source lang ="c"><br />
//****************************************************************************<br />
// * <br />
// * Von Gruppe 1<br />
// * Aufgabe: Alle LEDs sollen zum blinken gebracht werden.<br />
// * <br />
// * Task: All LED shall blink.<br />
// * <br />
//****************************************************************************<br />
<br />
#include <avr/io.h><br />
#include <util/delay.h><br />
<br />
int main(void)<br />
{<br />
/* LED Anschluss */<br />
/* LED output */<br />
/* LED1 PC4 */ <br />
/* LED2 PD3 */<br />
/* LED3 PD6 */<br />
/* LED4 PD7 */<br />
<br />
<br />
/* Setze Ports PC4, PD3, PD6 und PD7 als Ausgang */<br />
/* Set ports PC4, PD3, PD6 and PD7 as outputs */<br />
DDRC = _BV(4);<br />
DDRD = _BV(7)|_BV(6)|_BV(3);<br />
<br />
while(1)<br />
{<br />
/* _delay_ms() verzögert um 10 Millisekunden */<br />
/* 50 * 10ms = 500ms */<br />
/* _delay_ms() delays for 10 Milliseconds */<br />
/* 50 * 10ms = 500ms */<br />
for (uint8_t i=0;i<50;i++) _delay_ms(10);<br />
<br />
/* Schalte zwischen 5V und 0V an den Ausgängen hin und her */<br />
/* Toggle 5V and 0V at the outputs */<br />
PORTC ^= _BV(4);<br />
PORTD ^= _BV(7)|_BV(6)|_BV(3);<br />
}<br />
return 0;<br />
}<br />
<br />
<br />
</source><br />
<br /><br />
<br />
=== LED - Einschalten ===<br />
: Aufgabe: Eine LED soll zum leuchten gebracht werden.<br />
: Code:<br />
<source lang ="c"><br />
//****************************************************************************<br />
// * <br />
// * Von Gruppe 1<br />
// * Aufgabe: Eine LED soll zum leuchten gebracht werden.<br />
// * <br />
//****************************************************************************<br />
<br />
#include <avr/io.h><br />
<br />
int main(void)<br />
{<br />
/* PC4 auf Ausgang */<br />
DDRC = &b10000; /* Alternativ Hex: 0xF oder Dezimal: 16 */<br />
/* 7 6 5 4 3 2 1 0 */<br />
/* 0 0 0 1 0 0 0 0 */<br />
<br />
/* PC4 einschalten */<br />
PORTD = &b10000;<br />
<br />
/* Endlosschleife */<br />
while(1) <br />
{<br />
}<br />
}<br />
<br />
</source><br />
=== LED - Lauflicht ===<br />
: Code:<br />
<source lang ="c"><br />
//****************************************************************************<br />
// * <br />
// * Von Gruppe 1<br />
// * <br />
//****************************************************************************<br />
<br />
#include <avr/io.h><br />
#include <util/delay.h><br />
<br />
int main(void)<br />
{<br />
unsigned int i;<br />
<br />
/* Setze Ports PC4, PD3, PD6 und PD7 als Ausgang */<br />
DDRC = (1<<DDC4);<br />
DDRD = (1<<DDD7)|(1<<DDD6)|(1<<DDD3);<br />
/* Setze Ports PC4, PD3, PD6 und PD7 auf low */<br />
PORTC = (0<<PC4);<br />
PORTD = (0<<PD7)|(0<<PD6)|(0<<PD3);<br />
<br />
while(1)<br />
{<br />
PORTC ^= _BV(PC4);<br />
for (i=0;i<50;i++) _delay_loop_2(0);<br />
PORTC ^= _BV(PC4);<br />
PORTD ^= _BV(PD3);<br />
for (i=0;i<50;i++) _delay_loop_2(0);<br />
PORTD ^= _BV(PD3);<br />
PORTD ^= _BV(PD6);<br />
for (i=0;i<50;i++) _delay_loop_2(0);<br />
PORTD ^= _BV(PD6);<br />
PORTD ^= _BV(PD7);<br />
for (i=0;i<50;i++) _delay_loop_2(0);<br />
PORTD ^= _BV(PD7);<br />
<br />
}<br />
return 0;<br />
}<br />
</source><br />
<br />
=== Blinksequenz aufzeichnen und später abspielen ===<br />
<source lang="c">#include <avr/io.h><br />
#include <util/delay.h><br />
<br />
#define SEQS 100<br />
<br />
typedef struct {<br />
uint8_t bstate;<br />
uint32_t dur;<br />
} seq_t;<br />
<br />
seq_t seq[SEQS];<br />
uint8_t count = 0;<br />
<br />
void wait(uint32_t ms);<br />
void record(void);<br />
void play(void);<br />
<br />
void wait(uint32_t ms) {<br />
uint32_t i;<br />
<br />
for (i = 0; i < ms; i++) {<br />
_delay_ms(1);<br />
}<br />
} <br />
<br />
void record(void) {<br />
<br />
uint32_t dur = 0;<br />
uint8_t bstate_prev = 0x00; // prev button state<br />
uint8_t bstate = 0x00; // current button state<br />
<br />
while (1) {<br />
bstate = 0x00;<br />
<br />
// S1<br />
if (~PINC & _BV(PC0)) {<br />
bstate |= 1 << 1;<br />
} <br />
<br />
// S2<br />
if (~PINC & _BV(PC1)) {<br />
bstate |= 1 << 2;<br />
}<br />
<br />
// S3<br />
if (~PINC & _BV(PC2)) {<br />
bstate |= 1 << 3;<br />
}<br />
<br />
// S4<br />
if (~PINC & _BV(PC3)) {<br />
bstate |= 1 << 4;<br />
}<br />
<br />
// omit first state<br />
if (count == 0 && bstate == 0x0) {<br />
continue;<br />
}<br />
<br />
if (count >= SEQS) {<br />
// overflow error => all LEDs on<br />
while (1) {<br />
PORTC |= _BV(PC4);<br />
PORTD |= _BV(PD3) | _BV(PD6) | _BV(PD7);<br />
}<br />
}<br />
<br />
if (bstate_prev == bstate) {<br />
if (dur + 50 > dur) {<br />
dur += 50;<br />
}<br />
<br />
if (bstate == 0x0 && count > 0 && dur >= 2000) {<br />
// no button was pressed for 2s<br />
return;<br />
}<br />
} else {<br />
// save state<br />
seq[count].bstate = bstate_prev;<br />
seq[count].dur = dur;<br />
count++;<br />
<br />
// prepare for next state<br />
dur = 0;<br />
bstate_prev = bstate;<br />
}<br />
<br />
wait(50);<br />
}<br />
}<br />
<br />
void play(void) {<br />
uint8_t i;<br />
<br />
while (1) {<br />
// PORTD |= _BV(PD7);<br />
<br />
for (i = 0; i < count; i++) {<br />
// LED1<br />
if (seq[i].bstate & 1 << 1) {<br />
PORTC |= _BV(PC4);<br />
} else {<br />
PORTC &= ~_BV(PC4);<br />
}<br />
<br />
// LED2<br />
if (seq[i].bstate & 1 << 2) {<br />
PORTD |= _BV(PD3);<br />
} else {<br />
PORTD &= ~_BV(PD3);<br />
}<br />
<br />
// LED3<br />
if (seq[i].bstate & 1 << 3) {<br />
PORTD |= _BV(PD6);<br />
} else {<br />
PORTD &= ~_BV(PD6);<br />
}<br />
<br />
// LED4<br />
if (seq[i].bstate & 1 << 4) {<br />
PORTD |= _BV(PD7);<br />
} else {<br />
PORTD &= ~_BV(PD7);<br />
}<br />
<br />
wait(seq[i].dur);<br />
}<br />
<br />
PORTC &= ~_BV(PC4);<br />
PORTD &= ~_BV(PD3) & ~_BV(PD6) & ~_BV(PD7);<br />
wait(300);<br />
<br />
}<br />
}<br />
<br />
<br />
int main(void) {<br />
DDRC |= _BV(PC4);<br />
DDRD |= _BV(PD3) | _BV(PD6) | _BV(PD7); // all LEDs are output<br />
<br />
DDRC &= ~_BV(PC0) & ~_BV(PC1) & ~_BV(PC2) & ~_BV(PC3); // S[1..4] are input<br />
PORTC |= _BV(PC0) | _BV(PC1) | _BV(PC2) | _BV(PC3); // use pullup for S[1..4]<br />
<br />
// wait for pullops to "settle down"<br />
wait(1000);<br />
<br />
while (1) { <br />
record();<br />
play();<br />
}<br />
}</source><br />
<br />
== 2. Abend ==<br />
<br />
Änderungen des IR-Signals werden aufgezeichnet, und auch zeitlich ausgewertet. Messung ist jedoch relativ ungenau. Implementation von Timer / Counter fehlt.<br />
<br />
<source lang ="c"><br />
/* ################################### */<br />
/* # IR-Empfang # */<br />
/* # Von Gruppe 1 # */<br />
/* ################################### */<br />
/* # Done: IR-Signale chronologisch # */<br />
/* # aufzeichnen # */<br />
/* ################################### */<br />
/* # Todo: Counter / Timer einbauen # */<br />
/* ################################### */<br />
<br />
<br />
#include <avr/io.h><br />
#include <string.h><br />
#include <stdio.h><br />
#include <avr/pgmspace.h><br />
#include <util/delay.h><br />
#include "uart.h"<br />
<br />
int main(void)<br />
{<br />
int status = 0;<br />
int counter = 0;<br />
/* initialize serial uart */<br />
uart_init();<br />
<br />
/* configure irrx as input */<br />
DDRC &= ~_BV(PC3);<br />
<br />
/* init led pin as output */<br />
DDRD |= _BV(PD3);<br />
<br />
while(1) {<br />
counter++;<br />
for (int i = 0; i<10; i++)<br />
{<br />
_delay_us(10);<br />
}<br />
/* if ir rx is high, turn off led */<br />
if (PINC & _BV(PC3)) {<br />
// Kein IR<br />
PORTD &= ~_BV(PD3);<br />
if (status == 1)<br />
{<br />
uart_printf("Ir jetzt aus %u\n",counter);<br />
counter = 0;<br />
}<br />
status = 0;<br />
<br />
} else {<br />
PORTD |= _BV(PD3);<br />
if (status == 0)<br />
{<br />
uart_printf("Ir jetzt an %u\n",counter);<br />
counter = 0;<br />
}<br />
status = 1;<br />
}<br />
}<br />
}<br />
</source><br />
<br />
== 3. Abend ==<br />
=== IR-Jammer ===<br />
Sendet, sobald er IR empfängt, für 1000ms und wartet dann 5ms, damit er das ausgesandte Signal nicht wieder empfängt.<br />
<br />
<source lang="c"><br />
#include <avr/io.h><br />
#include <avr/interrupt.h><br />
#include <util/delay.h><br />
#include "uart.h"<br />
<br />
/* constants */<br />
#define MAX 160<br />
/* 38khz: freq = F_CPU/(2*prescaler*frequency)<br />
* 20mhz/(2*8*38khz) = ~33<br />
* real frequency: 20mhz/(2*8*33) = ~37878Hz */<br />
#define PWM_FREQ 33<br />
<br />
/* global variables */<br />
<br />
/* allocate 160*2 = 320 byte memory for storing a code,<br />
* this means we can store 80 on/off sequence timings */<br />
volatile uint16_t code[MAX];<br />
/* current index in code[] (default: 0) */<br />
volatile uint8_t pos = 0;<br />
/* current pin state (default: high == idle) */<br />
volatile uint8_t state = 1;<br />
/* signal for the main application that a code has been received<br />
* (default: 0) */<br />
volatile uint8_t done = 0;<br />
/* signal button presses from interrupt to main */<br />
volatile uint8_t button_press;<br />
/* current system mode */<br />
enum {<br />
MODE_OFF = 0,<br />
MODE_DISPLAY = 1,<br />
MODE_JAM = 2,<br />
MODE_RECORD = 3,<br />
} mode = MODE_DISPLAY;<br />
/* current viewmode */<br />
enum {<br />
VIEW_VALUE_AND_TIME = 0,<br />
VIEW_VALUE = 1,<br />
VIEW_TIME = 2,<br />
} view = VIEW_VALUE_AND_TIME;<br />
<br />
/* call every 10 ms, for buttons at pins PC0-PC3 */<br />
static uint8_t button_sample(void)<br />
{<br />
/* initialize state, buttons are active low! */<br />
static uint8_t btn_state = 15; //0b1111;<br />
/* initialize old sample */<br />
static uint8_t last_sample = 15; //0b1111;<br />
/* read inputs */<br />
uint8_t new_sample = PINC & 15; //0b1111;<br />
<br />
/* mark bits which are sampled with the same value */<br />
uint8_t same_sample = (last_sample ^ ~new_sample);<br />
/* all bits set in same_sample now have been sampled with the same value<br />
* at least two times, which means the button has settled */<br />
<br />
/* compare the current button state with the most recent sampled value,<br />
* but only for those bits which have stayed the same */<br />
uint8_t state_different = btn_state ^ (new_sample & same_sample);<br />
/* all bits set in state_different have been sampled at least two times<br />
* with the same value, and this value is different from the current<br />
* button state */<br />
<br />
/* if a bit is set in state (means: button is not pressed) AND bit is set<br />
* in state_different (means: input has settled and value is different<br />
* from state) together means: button has been pressed recently */<br />
uint8_t btn_press = btn_state & state_different;<br />
<br />
/* toggle all bits for inputs which switched state */<br />
btn_state ^= state_different;<br />
<br />
/* store current sample for next time */<br />
last_sample = new_sample;<br />
<br />
/* if bit is set in btn_press, a button has been pressed<br />
* (not released yet) */<br />
return btn_press;<br />
}<br />
<br />
void wait(uint32_t s) {<br />
uint32_t i;<br />
for (i = 0; i < s; i++) {<br />
_delay_ms(1);<br />
}<br />
}<br />
<br />
/* set up timer 0 to generate a carrier using pwm at freq on pin OC0B (PD5) */<br />
static void ir_enable(uint8_t freq) {<br />
/* timer 0: fast pwm mode, clear OC0B on match, prescaler 8 */<br />
TCCR0A = _BV(WGM00) | _BV(COM0B1);<br />
TCCR0B = _BV(CS01) | _BV(WGM02);<br />
<br />
/* set frequency */<br />
OCR0A = freq;<br />
<br />
/* set duty-cycle to 50% */<br />
OCR0B = freq/2;<br />
}<br />
<br />
/* disable timer 0 and pwm generation */<br />
static void ir_disable(void) {<br />
TCCR0A = 0;<br />
TCCR0B = 0;<br />
}<br />
<br />
<br />
/* pin change interrupt 1 service function */<br />
ISR(PCINT1_vect)<br />
{<br />
/* do nothing if we are just processing a code in the main loop,<br />
* or no more space is available for a timer value */<br />
if (done || pos == MAX)<br />
return;<br />
<br />
/* if this would be the first timing value ever recorded, and the<br />
* state before was high (=idle), do not record the timing value<br />
* and just reset the timer */<br />
if (state && pos == 0) {<br />
TCNT1 = 0;<br />
/* else record the timing value */<br />
} else {<br />
/* store current timer value in code[]<br />
* and reset the timer */<br />
code[pos++] = TCNT1;<br />
TCNT1 = 0;<br />
}<br />
<br />
/* toggle second led */<br />
PORTD ^= _BV(PD3);<br />
<br />
/* toggle state */<br />
state = !state;<br />
}<br />
<br />
/* timer 1 compare A interrupt service function */<br />
ISR(TIMER1_COMPA_vect)<br />
{<br />
/* do nothing if we are just processing a code in the main loop */<br />
if (done)<br />
return;<br />
<br />
/* if some code has been received */<br />
if (pos > 0) {<br />
/* if pos is odd, one last 'off'-timing is missing, fill with zero */<br />
if (pos % 2 == 1)<br />
code[pos++] = 0;<br />
<br />
/* signal main */<br />
done = 1;<br />
<br />
/* turn on third led */<br />
PORTD |= _BV(PD6);<br />
}<br />
}<br />
<br />
/* timer 2 compare A interrupt service function */<br />
ISR(TIMER2_COMPA_vect)<br />
{<br />
/* sample buttons every 10ms */<br />
button_press |= button_sample();<br />
}<br />
<br />
int main(void)<br />
{<br />
/* initialize uart */<br />
uart_init();<br />
uart_printf("rumpus ir analyzer\n");<br />
<br />
/* configure led pins as outputs and turn leds off */<br />
DDRC |= _BV(PC4);<br />
DDRD |= _BV(PD3) | _BV(PD6) | _BV(PD7);<br />
PORTC &= ~_BV(PC4);<br />
PORTD &= ~(_BV(PD3) | _BV(PD6) | _BV(PD7));<br />
<br />
/* configure ir input pin, with pullup */<br />
DDRC &= ~_BV(PC3);<br />
PORTC |= _BV(PC3);<br />
<br />
/* configure button input pins, with pullup */<br />
DDRC &= ~(_BV(PC0) | _BV(PC1) | _BV(PC2) | _BV(PC3));<br />
PORTC |= _BV(PC0) | _BV(PC1) | _BV(PC2) | _BV(PC3);<br />
<br />
/* configure ir send pin as output, set low */<br />
DDRD |= _BV(PD5);<br />
PORTD &= ~_BV(PD5);<br />
<br />
/* wait until pin is high (no ir carrier is detected) */<br />
while(!(PINC & _BV(PC3)));<br />
<br />
/* enable pin change interrupt 1 for ir input pin (PC3/PCINT11) */<br />
PCMSK1 |= _BV(PCINT11);<br />
PCICR |= _BV(PCIE1);<br />
<br />
/* configure timer1 with prescaler 64 and CTC for measuring ir timings */<br />
TCCR1B = _BV(CS11) | _BV(CS10) | _BV(WGM12);<br />
/* configure timer action after 200ms: 20mhz/64/5 */<br />
OCR1A = F_CPU/5/64;<br />
/* enable OCR1A interrupt */<br />
TIMSK1 = _BV(OCIE1A);<br />
<br />
/* configure timer 2 with prescaler 1024 and CTC<br />
* for button sampling */<br />
TCCR2A = _BV(WGM21);<br />
TCCR2B = _BV(CS22) | _BV(CS21) | _BV(CS20);<br />
/* configure compare event a to occur after 10ms and enable interrupt */<br />
OCR2A = F_CPU/1024/100;<br />
TIMSK2 = _BV(OCIE2A);<br />
<br />
/* signal user availability by turning on led 1 */<br />
PORTC |= _BV(PC4);<br />
<br />
/* enable interrupts */<br />
sei();<br />
<br />
/* signal the user that the analyzer part has started by turning led 1 on */<br />
PORTC |= _BV(PC3);<br />
<br />
while(1) {<br />
/* if a code has been received */<br />
if (mode == MODE_DISPLAY && done) {<br />
<br />
/* print code to serial uart */<br />
uart_printf("complete code received, %u on-off-timings:\n", pos/2);<br />
for (uint8_t i = 0; i < pos; i += 2) {<br />
<br />
if (view == VIEW_VALUE_AND_TIME) {<br />
uint32_t on, off;<br />
<br />
/* compute timing in microseconds */<br />
on = ((uint32_t)code[i]) * 64 / 20;<br />
off = ((uint32_t)code[i+1]) * 64 / 20;<br />
<br />
uart_printf(" %5lu us (%5u) on, %5lu us (%5u) off\n",<br />
on, code[i],<br />
off, code[i+1]);<br />
} else if (view == VIEW_VALUE) {<br />
uart_printf(" %5u on, %5u off\n",<br />
code[i], code[i+1]);<br />
} else if (view == VIEW_TIME) {<br />
uint32_t on, off;<br />
<br />
/* compute timing in microseconds */<br />
on = ((uint32_t)code[i]) * 64 / 20;<br />
off = ((uint32_t)code[i+1]) * 64 / 20;<br />
<br />
uart_printf(" %5lu us on, %5lu us off\n",<br />
on, off);<br />
}<br />
}<br />
<br />
<br />
/* turn off second and third led */<br />
PORTD &= ~(_BV(PD3) | _BV(PD6));<br />
<br />
/* wait until pin is high (no ir carrier is detected) */<br />
while(!(PINC & _BV(PC3)));<br />
<br />
/* reset all global variables */<br />
pos = 0;<br />
state = 1;<br />
done = 0;<br />
}<br />
<br />
if (mode == MODE_JAM) {<br />
// hier wird gejammt!<br />
<br />
if (!state) {<br />
DDRC |= _BV(PC3); // ir empfang aus<br />
<br />
ir_enable(PWM_FREQ);<br />
wait(1000);<br />
ir_disable();<br />
<br />
wait(5); // damit wir unser eben gesendetes signal nicht empfangen<br />
DDRC &= ~_BV(PC3); // ir empfang an<br />
<br />
done = 0;<br />
pos = 0;<br />
}<br />
}<br />
<br />
if (button_press) {<br />
/* first button toggles system mode */<br />
if (button_press & 1) {<br />
mode++;<br />
if (mode > MODE_RECORD)<br />
mode = MODE_OFF;<br />
<br />
if (mode == MODE_OFF) {<br />
uart_printf("ir analyzer switched off\n");<br />
<br />
/* disable timer1 and pin change interrupts */<br />
TIMSK1 &= ~_BV(OCIE1A);<br />
PCMSK1 &= ~_BV(PCINT11);<br />
<br />
/* turn off led1 */<br />
PORTC &= ~_BV(PC4);<br />
<br />
} else if (mode == MODE_DISPLAY) {<br />
uart_printf("scan and display codes\n");<br />
<br />
/* clear interrupt flags, enable timer1 and pin change interrupts */<br />
TIFR1 = _BV(OCIE1A);<br />
TIMSK1 |= _BV(OCIE1A);<br />
PCMSK1 |= _BV(PCINT11);<br />
<br />
/* turn on led1 */<br />
PORTC |= _BV(PC4);<br />
} else if (mode == MODE_JAM) {<br />
/* clear interrupt flags, enable timer1 and pin change interrupts */<br />
TIFR1 = _BV(OCIE1A);<br />
TIMSK1 |= _BV(OCIE1A);<br />
PCMSK1 |= _BV(PCINT11);<br />
<br />
uart_printf("jamming mode active\n");<br />
} else if (mode == MODE_RECORD) {<br />
uart_printf("record and replay a code\n");<br />
}<br />
}<br />
<br />
<br />
/* second button toggles view mode */<br />
if (button_press & 2) {<br />
view++;<br />
if (view > VIEW_TIME)<br />
view = VIEW_VALUE_AND_TIME;<br />
<br />
if (view == VIEW_VALUE_AND_TIME)<br />
uart_printf("display timer value and time (in us)\n");<br />
else if (view == VIEW_VALUE)<br />
uart_printf("display timer value\n");<br />
else if (view == VIEW_TIME)<br />
uart_printf("display time (in us)\n");<br />
}<br />
<br />
if (button_press & 4) {<br />
static uint8_t pwm = 0;<br />
<br />
if (!pwm) {<br />
ir_enable(PWM_FREQ);<br />
uart_printf("pwm on\n");<br />
} else {<br />
ir_disable();<br />
uart_printf("pwm off\n");<br />
}<br />
pwm = !pwm;<br />
}<br />
<br />
button_press = 0;<br />
}<br />
}<br />
}</source><br />
<br />
== 4. Abend ==<br />
=== IR-Jammer in schlau ===<br />
Misst die kürzeste Impulsdauer und sendet mit dieser (plus einer kleinen, sich ändernden Verzögerung) in die Pausen.<br />
<br />
<source lang="c">#include <avr/io.h><br />
#include <avr/interrupt.h><br />
#include <util/delay.h><br />
#include "uart.h"<br />
<br />
/* constants */<br />
#define MAX 160<br />
/* 38khz: freq = F_CPU/(2*prescaler*frequency)<br />
* 20mhz/(2*8*38khz) = ~33<br />
* real frequency: 20mhz/(2*8*33) = ~37878Hz */<br />
#define PWM_FREQ 33<br />
<br />
/* global variables */<br />
<br />
/* allocate 160*2 = 320 byte memory for storing a code,<br />
* this means we can store 80 on/off sequence timings */<br />
volatile uint16_t code[MAX];<br />
/* current index in code[] (default: 0) */<br />
volatile uint8_t pos = 0;<br />
/* current pin state (default: high == idle) */<br />
volatile uint8_t state = 1;<br />
/* signal for the main application that a code has been received<br />
* (default: 0) */<br />
volatile uint8_t done = 0;<br />
/* signal button presses from interrupt to main */<br />
volatile uint8_t button_press;<br />
/* current system mode */<br />
enum {<br />
MODE_OFF = 0,<br />
MODE_DISPLAY = 1,<br />
MODE_JAM = 2,<br />
MODE_RECORD = 3,<br />
} mode = MODE_DISPLAY;<br />
/* current viewmode */<br />
enum {<br />
VIEW_VALUE_AND_TIME = 0,<br />
VIEW_VALUE = 1,<br />
VIEW_TIME = 2,<br />
} view = VIEW_VALUE_AND_TIME;<br />
<br />
/* call every 10 ms, for buttons at pins PC0-PC3 */<br />
static uint8_t button_sample(void)<br />
{<br />
/* initialize state, buttons are active low! */<br />
static uint8_t btn_state = 15; //0b1111;<br />
/* initialize old sample */<br />
static uint8_t last_sample = 15; //0b1111;<br />
/* read inputs */<br />
uint8_t new_sample = PINC & 15; //0b1111;<br />
<br />
/* mark bits which are sampled with the same value */<br />
uint8_t same_sample = (last_sample ^ ~new_sample);<br />
/* all bits set in same_sample now have been sampled with the same value<br />
* at least two times, which means the button has settled */<br />
<br />
/* compare the current button state with the most recent sampled value,<br />
* but only for those bits which have stayed the same */<br />
uint8_t state_different = btn_state ^ (new_sample & same_sample);<br />
/* all bits set in state_different have been sampled at least two times<br />
* with the same value, and this value is different from the current<br />
* button state */<br />
<br />
/* if a bit is set in state (means: button is not pressed) AND bit is set<br />
* in state_different (means: input has settled and value is different<br />
* from state) together means: button has been pressed recently */<br />
uint8_t btn_press = btn_state & state_different;<br />
<br />
/* toggle all bits for inputs which switched state */<br />
btn_state ^= state_different;<br />
<br />
/* store current sample for next time */<br />
last_sample = new_sample;<br />
<br />
/* if bit is set in btn_press, a button has been pressed<br />
* (not released yet) */<br />
return btn_press;<br />
}<br />
<br />
static void wait(uint32_t s) {<br />
uint32_t i;<br />
for (i = 0; i < s; i++) {<br />
_delay_us(1);<br />
}<br />
}<br />
<br />
/* set up timer 0 to generate a carrier using pwm at freq on pin OC0B (PD5) */<br />
static void ir_enable(uint8_t freq) {<br />
/* timer 0: fast pwm mode, clear OC0B on match, prescaler 8 */<br />
TCCR0A = _BV(WGM00) | _BV(COM0B1);<br />
TCCR0B = _BV(CS01) | _BV(WGM02);<br />
<br />
/* set frequency */<br />
OCR0A = freq;<br />
<br />
/* set duty-cycle to 50% */<br />
OCR0B = freq/2;<br />
}<br />
<br />
/* disable timer 0 and pwm generation */<br />
static void ir_disable(void) {<br />
TCCR0A = 0;<br />
TCCR0B = 0;<br />
}<br />
<br />
static void jam(void) {<br />
static uint32_t dur;<br />
static uint16_t i;<br />
uint8_t j = 0;<br />
uint32_t dur_tmp;<br />
<br />
if (pos == 0 || done) {<br />
dur = 0xFFFFFFFF;<br />
}<br />
<br />
if (i % 500 == 0) {<br />
i=0;<br />
if (!state) {<br />
uart_printf("-");<br />
} else {<br />
uart_printf(".");<br />
}<br />
}<br />
i++;<br />
<br />
<br />
if (pos < 1) {<br />
return;<br />
}<br />
<br />
// shortest measured duration<br />
dur_tmp = ((uint32_t)code[pos-1]) * 64 / 20;<br />
dur = dur_tmp < dur ? dur_tmp : dur;<br />
<br />
while (!state && j < 10) {<br />
j++;<br />
DDRC |= _BV(PC3); // ir reciever off<br />
<br />
ir_enable(PWM_FREQ);<br />
uart_printf("*");<br />
wait(dur+i);<br />
ir_disable();<br />
<br />
wait(250); // we don't want to recieve our own signal (due to lags in the ir receiver)<br />
DDRC &= ~_BV(PC3); // ir reciever on<br />
}<br />
}<br />
<br />
/* pin change interrupt 1 service function */<br />
ISR(PCINT1_vect)<br />
{<br />
/* do nothing if we are just processing a code in the main loop,<br />
* or no more space is available for a timer value */<br />
if (done || pos == MAX)<br />
return;<br />
<br />
/* if this would be the first timing value ever recorded, and the<br />
* state before was high (=idle), do not record the timing value<br />
* and just reset the timer */<br />
if (state && pos == 0) {<br />
TCNT1 = 0;<br />
/* else record the timing value */<br />
} else {<br />
/* store current timer value in code[]<br />
* and reset the timer */<br />
code[pos++] = TCNT1;<br />
TCNT1 = 0;<br />
}<br />
<br />
/* toggle second led */<br />
PORTD ^= _BV(PD3);<br />
<br />
/* toggle state */<br />
state = !state;<br />
}<br />
<br />
/* timer 1 compare A interrupt service function */<br />
ISR(TIMER1_COMPA_vect)<br />
{<br />
/* do nothing if we are just processing a code in the main loop */<br />
if (done)<br />
return;<br />
<br />
/* if some code has been received */<br />
if (pos > 0) {<br />
/* if pos is odd, one last 'off'-timing is missing, fill with zero */<br />
if (pos % 2 == 1)<br />
code[pos++] = 0;<br />
<br />
/* signal main */<br />
done = 1;<br />
<br />
/* turn on third led */<br />
PORTD |= _BV(PD6);<br />
}<br />
}<br />
<br />
/* timer 2 compare A interrupt service function */<br />
ISR(TIMER2_COMPA_vect)<br />
{<br />
/* sample buttons every 10ms */<br />
button_press |= button_sample();<br />
}<br />
<br />
int main(void)<br />
{<br />
/* initialize uart */<br />
uart_init();<br />
uart_printf("rumpus ir analyzer\n");<br />
<br />
/* configure led pins as outputs and turn leds off */<br />
DDRC |= _BV(PC4);<br />
DDRD |= _BV(PD3) | _BV(PD6) | _BV(PD7);<br />
PORTC &= ~_BV(PC4);<br />
PORTD &= ~(_BV(PD3) | _BV(PD6) | _BV(PD7));<br />
<br />
/* configure ir input pin, with pullup */<br />
DDRC &= ~_BV(PC3);<br />
PORTC |= _BV(PC3);<br />
<br />
/* configure button input pins, with pullup */<br />
DDRC &= ~(_BV(PC0) | _BV(PC1) | _BV(PC2) | _BV(PC3));<br />
PORTC |= _BV(PC0) | _BV(PC1) | _BV(PC2) | _BV(PC3);<br />
<br />
/* configure ir send pin as output, set low */<br />
DDRD |= _BV(PD5);<br />
PORTD &= ~_BV(PD5);<br />
<br />
/* wait until pin is high (no ir carrier is detected) */<br />
while(!(PINC & _BV(PC3)));<br />
<br />
/* enable pin change interrupt 1 for ir input pin (PC3/PCINT11) */<br />
PCMSK1 |= _BV(PCINT11);<br />
PCICR |= _BV(PCIE1);<br />
<br />
/* configure timer1 with prescaler 64 and CTC for measuring ir timings */<br />
TCCR1B = _BV(CS11) | _BV(CS10) | _BV(WGM12);<br />
/* configure timer action after 200ms: 20mhz/64/5 */<br />
OCR1A = F_CPU/5/64;<br />
/* enable OCR1A interrupt */<br />
TIMSK1 = _BV(OCIE1A);<br />
<br />
/* configure timer 2 with prescaler 1024 and CTC<br />
* for button sampling */<br />
TCCR2A = _BV(WGM21);<br />
TCCR2B = _BV(CS22) | _BV(CS21) | _BV(CS20);<br />
/* configure compare event a to occur after 10ms and enable interrupt */<br />
OCR2A = F_CPU/1024/100;<br />
TIMSK2 = _BV(OCIE2A);<br />
<br />
/* signal user availability by turning on led 1 */<br />
PORTC |= _BV(PC4);<br />
<br />
/* enable interrupts */<br />
sei();<br />
<br />
/* signal the user that the analyzer part has started by turning led 1 on */<br />
PORTC |= _BV(PC3);<br />
<br />
while(1) {<br />
/* if a code has been received */<br />
if (mode == MODE_DISPLAY && done) {<br />
<br />
/* print code to serial uart */<br />
uart_printf("complete code received, %u on-off-timings:\n", pos/2);<br />
for (uint8_t i = 0; i < pos; i += 2) {<br />
<br />
if (view == VIEW_VALUE_AND_TIME) {<br />
uint32_t on, off;<br />
<br />
/* compute timing in microseconds */<br />
on = ((uint32_t)code[i]) * 64 / 20;<br />
off = ((uint32_t)code[i+1]) * 64 / 20;<br />
<br />
uart_printf(" %5lu us (%5u) on, %5lu us (%5u) off\n",<br />
on, code[i],<br />
off, code[i+1]);<br />
} else if (view == VIEW_VALUE) {<br />
uart_printf(" %5u on, %5u off\n",<br />
code[i], code[i+1]);<br />
} else if (view == VIEW_TIME) {<br />
uint32_t on, off;<br />
<br />
/* compute timing in microseconds */<br />
on = ((uint32_t)code[i]) * 64 / 20;<br />
off = ((uint32_t)code[i+1]) * 64 / 20;<br />
<br />
uart_printf(" %5lu us on, %5lu us off\n",<br />
on, off);<br />
}<br />
}<br />
<br />
<br />
/* turn off second and third led */<br />
PORTD &= ~(_BV(PD3) | _BV(PD6));<br />
<br />
/* wait until pin is high (no ir carrier is detected) */<br />
while(!(PINC & _BV(PC3)));<br />
<br />
/* reset all global variables */<br />
pos = 0;<br />
state = 1;<br />
done = 0;<br />
}<br />
<br />
if (mode == MODE_JAM) {<br />
jam();<br />
}<br />
<br />
if (done) {<br />
// code completely detected<br />
<br />
/* reset all global variables */<br />
pos = 0;<br />
state = 1;<br />
done = 0;<br />
} <br />
<br />
if (button_press) {<br />
/* first button toggles system mode */<br />
if (button_press & 1) {<br />
mode++;<br />
if (mode > MODE_RECORD)<br />
mode = MODE_OFF;<br />
<br />
if (mode == MODE_OFF) {<br />
uart_printf("ir analyzer switched off\n");<br />
<br />
/* disable timer1 and pin change interrupts */<br />
TIMSK1 &= ~_BV(OCIE1A);<br />
PCMSK1 &= ~_BV(PCINT11);<br />
<br />
/* turn off led1 */<br />
PORTC &= ~_BV(PC4);<br />
<br />
} else if (mode == MODE_DISPLAY) {<br />
uart_printf("scan and display codes\n");<br />
<br />
/* clear interrupt flags, enable timer1 and pin change interrupts */<br />
TIFR1 = _BV(OCIE1A);<br />
TIMSK1 |= _BV(OCIE1A);<br />
PCMSK1 |= _BV(PCINT11);<br />
<br />
/* turn on led1 */<br />
PORTC |= _BV(PC4);<br />
} else if (mode == MODE_JAM) {<br />
/* clear interrupt flags, enable timer1 and pin change interrupts */<br />
TIFR1 = _BV(OCIE1A);<br />
TIMSK1 |= _BV(OCIE1A);<br />
PCMSK1 |= _BV(PCINT11);<br />
<br />
uart_printf("jamming mode active\n");<br />
} else if (mode == MODE_RECORD) {<br />
uart_printf("record and replay a code\n");<br />
}<br />
}<br />
<br />
<br />
/* second button toggles view mode */<br />
if (button_press & 2) {<br />
view++;<br />
if (view > VIEW_TIME)<br />
view = VIEW_VALUE_AND_TIME;<br />
<br />
if (view == VIEW_VALUE_AND_TIME)<br />
uart_printf("display timer value and time (in us)\n");<br />
else if (view == VIEW_VALUE)<br />
uart_printf("display timer value\n");<br />
else if (view == VIEW_TIME)<br />
uart_printf("display time (in us)\n");<br />
}<br />
<br />
if (button_press & 4) {<br />
static uint8_t pwm = 0;<br />
<br />
if (!pwm) {<br />
ir_enable(PWM_FREQ);<br />
uart_printf("pwm on\n");<br />
} else {<br />
ir_disable();<br />
uart_printf("pwm off\n");<br />
}<br />
pwm = !pwm;<br />
}<br />
<br />
button_press = 0;<br />
}<br />
}<br />
}</source><br />
<br />
=== Eigener Chat ===<br />
Hier wird die neue uart.c benutzt (die mit Senden und Empfangen). Leider funktioniert der Chat dann nicht mehr, vermutlich kommt der neue uart-Interrupt der wait-Funktion in die Query. Wenn man die alte uart.c benutzt kann man sich wunderbar über die 4 Taster unterhalten :) [[User:Hendi|Hendi]]<br />
<br />
<source lang="c">#include <avr/io.h><br />
#include <avr/interrupt.h><br />
#include <util/delay.h><br />
#include "uart.h"<br />
<br />
/* constants */<br />
#define MAX 160<br />
/* 38khz: freq = F_CPU/(2*prescaler*frequency)<br />
* 20mhz/(2*8*38khz) = ~33<br />
* real frequency: 20mhz/(2*8*33) = ~37878Hz */<br />
#define PWM_FREQ 33<br />
<br />
/* global variables */<br />
<br />
/* allocate 160*2 = 320 byte memory for storing a code,<br />
* this means we can store 80 on/off sequence timings */<br />
volatile uint16_t code[MAX];<br />
/* current index in code[] (default: 0) */<br />
volatile uint8_t pos = 0;<br />
/* current pin state (default: high == idle) */<br />
volatile uint8_t state = 1;<br />
/* signal for the main application that a code has been received<br />
* (default: 0) */<br />
volatile uint8_t done = 0;<br />
/* signal button presses from interrupt to main */<br />
volatile uint8_t button_press;<br />
/* current system mode */<br />
enum {<br />
MODE_OFF = 0,<br />
MODE_DISPLAY = 1,<br />
MODE_JAM = 2,<br />
MODE_RECORD = 3,<br />
} mode = MODE_DISPLAY;<br />
/* current viewmode */<br />
enum {<br />
VIEW_VALUE_AND_TIME = 0,<br />
VIEW_VALUE = 1,<br />
VIEW_TIME = 2,<br />
} view = VIEW_VALUE_AND_TIME;<br />
<br />
/* call every 10 ms, for buttons at pins PC0-PC3 */<br />
static uint8_t button_sample(void)<br />
{<br />
/* initialize state, buttons are active low! */<br />
static uint8_t btn_state = 15; //0b1111;<br />
/* initialize old sample */<br />
static uint8_t last_sample = 15; //0b1111;<br />
/* read inputs */<br />
uint8_t new_sample = PINC & 15; //0b1111;<br />
<br />
/* mark bits which are sampled with the same value */<br />
uint8_t same_sample = (last_sample ^ ~new_sample);<br />
/* all bits set in same_sample now have been sampled with the same value<br />
* at least two times, which means the button has settled */<br />
<br />
/* compare the current button state with the most recent sampled value,<br />
* but only for those bits which have stayed the same */<br />
uint8_t state_different = btn_state ^ (new_sample & same_sample);<br />
/* all bits set in state_different have been sampled at least two times<br />
* with the same value, and this value is different from the current<br />
* button state */<br />
<br />
/* if a bit is set in state (means: button is not pressed) AND bit is set<br />
* in state_different (means: input has settled and value is different<br />
* from state) together means: button has been pressed recently */<br />
uint8_t btn_press = btn_state & state_different;<br />
<br />
/* toggle all bits for inputs which switched state */<br />
btn_state ^= state_different;<br />
<br />
/* store current sample for next time */<br />
last_sample = new_sample;<br />
<br />
/* if bit is set in btn_press, a button has been pressed<br />
* (not released yet) */<br />
return btn_press;<br />
}<br />
<br />
static void wait(uint32_t s) {<br />
uint32_t i;<br />
s /= 100;<br />
s *= 2.75;<br />
for (i = 0; i < s; i++) {<br />
_delay_us(100);<br />
}<br />
}<br />
<br />
/* set up timer 0 to generate a carrier using pwm at freq on pin OC0B (PD5) */<br />
static void ir_enable(uint8_t freq) {<br />
/* timer 0: fast pwm mode, clear OC0B on match, prescaler 8 */<br />
TCCR0A = _BV(WGM00) | _BV(COM0B1);<br />
TCCR0B = _BV(CS01) | _BV(WGM02);<br />
<br />
/* set frequency */<br />
OCR0A = freq;<br />
<br />
/* set duty-cycle to 1/4 */<br />
OCR0B = freq/4;<br />
}<br />
<br />
/* disable timer 0 and pwm generation */<br />
static void ir_disable(void) {<br />
TCCR0A = 0;<br />
TCCR0B = 0;<br />
}<br />
<br />
<br />
/* pin change interrupt 1 service function */<br />
ISR(PCINT1_vect)<br />
{<br />
/* do nothing if we are just processing a code in the main loop,<br />
* or no more space is available for a timer value */<br />
if (done || pos == MAX)<br />
return;<br />
<br />
/* if this would be the first timing value ever recorded, and the<br />
* state before was high (=idle), do not record the timing value<br />
* and just reset the timer */<br />
if (state && pos == 0) {<br />
TCNT1 = 0;<br />
/* else record the timing value */<br />
} else {<br />
/* store current timer value in code[]<br />
* and reset the timer */<br />
code[pos++] = TCNT1;<br />
TCNT1 = 0;<br />
}<br />
<br />
/* toggle second led */<br />
PORTD ^= _BV(PD3);<br />
<br />
/* toggle state */<br />
state = !state;<br />
}<br />
<br />
/* timer 1 compare A interrupt service function */<br />
ISR(TIMER1_COMPA_vect)<br />
{<br />
/* do nothing if we are just processing a code in the main loop */<br />
if (done)<br />
return;<br />
<br />
/* if some code has been received */<br />
if (pos > 0) {<br />
/* if pos is odd, one last 'off'-timing is missing, fill with zero */<br />
if (pos % 2 == 1)<br />
code[pos++] = 0;<br />
<br />
/* signal main */<br />
done = 1;<br />
<br />
/* turn on third led */<br />
PORTD |= _BV(PD6);<br />
}<br />
}<br />
<br />
/* timer 2 compare A interrupt service function */<br />
ISR(TIMER2_COMPA_vect)<br />
{<br />
/* sample buttons every 10ms */<br />
button_press |= button_sample();<br />
}<br />
<br />
// NEC protocol, see http://www.sbprojects.com/knowledge/ir/nec.htm<br />
static void send1(void) {<br />
// uart_printf("1");<br />
ir_enable(PWM_FREQ);<br />
wait(560);<br />
ir_disable();<br />
wait(560);<br />
wait(560);<br />
}<br />
<br />
static void send0(void) {<br />
// uart_printf("0");<br />
ir_enable(PWM_FREQ);<br />
wait(560);<br />
ir_disable();<br />
wait(560);<br />
}<br />
<br />
static void send(uint8_t msg[]) {<br />
uint8_t sendcode;<br />
<br />
while(!(PINC & _BV(PC3)));<br />
<br />
// say hello<br />
ir_enable(PWM_FREQ);<br />
wait(9000);<br />
ir_disable();<br />
wait(4500);<br />
<br />
for (uint8_t z=0; z<100; z++) {<br />
if (msg[z] == '\r') {<br />
z=100;<br />
}<br />
<br />
sendcode = msg[z];<br />
<br />
// send data<br />
for (uint8_t i=0; i<8; i++) {<br />
if (sendcode & (1 << i)) {<br />
send1();<br />
} else {<br />
send0();<br />
}<br />
}<br />
}<br />
<br />
// enable IR, so we know how long it was off<br />
ir_enable(PWM_FREQ);<br />
wait(560);<br />
ir_disable();<br />
wait(560);<br />
}<br />
<br />
static void receive(void) {<br />
uint8_t rcv;<br />
<br />
//uart_printf("-- %d --\n", pos);<br />
while(!(PINC & _BV(PC3)));<br />
<br />
// transform time to ms<br />
for (uint8_t i = 0; i < pos; i++) {<br />
code[i] *= 64 / 20;<br />
}<br />
<br />
// receive hello<br />
if (code[0] < 8500 || code[0] > 9500<br />
|| code[1] < 4000 || code[1] > 5000<br />
|| pos < 10<br />
) {<br />
// no nec hello found<br />
uart_printf("no nec\n");<br />
// return;<br />
}<br />
<br />
// receive msg<br />
for (uint8_t j=0; j<pos/8; j++) {<br />
for (uint8_t i=0; i<8; i++) {<br />
uart_printf("%d - ", code[16*j + 2*i + 2]);<br />
uart_printf("%d", code[16*j + 2*i + 3]);<br />
//uart_printf(" ----- ");<br />
<br />
if (!(code[16*j + 2*i + 2] > 400 && code[16*j + 2*i + 2] < 800)) {<br />
// bit doesn't start with ON<br />
rcv = ' '; //uart_printf(" off FAIL (%d)\n", code[16*j + 2*i +2]);<br />
<br />
i=8; continue; // go to next byte<br />
}<br />
<br />
if (code[16*j + 2*i + 3] > 400 && code[16*j + 2*i + 3] < 800) {<br />
// bit is 0<br />
rcv &= ~(1 << i);<br />
} else if (code[16*j + 2*i + 3] > 900 && code[16*j + 2*i + 3] < 1300) {<br />
// bit is 1<br />
rcv |= 1 << i;<br />
} else {<br />
// not sure which value we have<br />
rcv = ' '; //uart_printf(" FAIL (%d)\n", code[16*j + 2*i + 3]);<br />
<br />
i=8; continue; // go to next byte<br />
}<br />
}<br />
uart_printf("%c", rcv);<br />
if (rcv == '\r') {<br />
j=pos/8;<br />
}<br />
uart_printf("\n");<br />
}<br />
<br />
}<br />
<br />
int main(void)<br />
{<br />
/* initialize uart */<br />
uart_init();<br />
uart_printf("rumpus ir chat\n");<br />
<br />
/* configure led pins as outputs and turn leds off */<br />
DDRC |= _BV(PC4);<br />
DDRD |= _BV(PD3) | _BV(PD6) | _BV(PD7);<br />
PORTC &= ~_BV(PC4);<br />
PORTD &= ~(_BV(PD3) | _BV(PD6) | _BV(PD7));<br />
<br />
/* configure ir input pin, with pullup */<br />
DDRC &= ~_BV(PC3);<br />
PORTC |= _BV(PC3);<br />
<br />
/* configure button input pins, with pullup */<br />
DDRC &= ~(_BV(PC0) | _BV(PC1) | _BV(PC2) | _BV(PC3));<br />
PORTC |= _BV(PC0) | _BV(PC1) | _BV(PC2) | _BV(PC3);<br />
<br />
/* configure ir send pin as output, set low */<br />
DDRD |= _BV(PD5);<br />
PORTD &= ~_BV(PD5);<br />
<br />
/* wait until pin is high (no ir carrier is detected) */<br />
while(!(PINC & _BV(PC3)));<br />
<br />
/* enable pin change interrupt 1 for ir input pin (PC3/PCINT11) */<br />
PCMSK1 |= _BV(PCINT11);<br />
PCICR |= _BV(PCIE1);<br />
<br />
/* configure timer1 with prescaler 64 and CTC for measuring ir timings */<br />
TCCR1B = _BV(CS11) | _BV(CS10) | _BV(WGM12);<br />
/* configure timer action after 200ms: 20mhz/64/5 */<br />
OCR1A = F_CPU/5/64;<br />
/* enable OCR1A interrupt */<br />
TIMSK1 = _BV(OCIE1A);<br />
<br />
/* configure timer 2 with prescaler 1024 and CTC<br />
* for button sampling */<br />
TCCR2A = _BV(WGM21);<br />
TCCR2B = _BV(CS22) | _BV(CS21) | _BV(CS20);<br />
/* configure compare event a to occur after 10ms and enable interrupt */<br />
OCR2A = F_CPU/1024/100;<br />
TIMSK2 = _BV(OCIE2A);<br />
<br />
/* signal user availability by turning on led 1 */<br />
PORTC |= _BV(PC4);<br />
<br />
/* enable interrupts */<br />
sei();<br />
<br />
/* signal the user that the analyzer part has started by turning led 1 on */<br />
PORTC |= _BV(PC3);<br />
<br />
while(1) {<br />
<br />
/* if a code has been received */<br />
if (done) {<br />
receive();<br />
uart_printf("\n");<br />
<br />
/* turn off second and third led */<br />
PORTD &= ~(_BV(PD3) | _BV(PD6));<br />
<br />
/* wait until pin is high (no ir carrier is detected) */<br />
while(!(PINC & _BV(PC3)));<br />
<br />
/* reset all global variables */<br />
pos = 0;<br />
state = 1;<br />
done = 0;<br />
}<br />
<br />
if (uart_done == 1) {<br />
send(uart_input);<br />
uart_len = 0;<br />
uart_done = 0;<br />
}<br />
<br />
if (button_press) {<br />
/* first button toggles system mode */<br />
uint8_t msg[7] = "Hallo!\r";<br />
// SENDE<br />
if (button_press & (1 << 0)) {<br />
send(msg);<br />
} else if (button_press & (1 << 1)) {<br />
send(("Gruppe 1\r")); // 0b101<br />
} else if (button_press & (1 << 2)) {<br />
send("1234567890\r"); // 0b10001<br />
} else if (button_press & (1 << 3)) {<br />
send("XY\r");<br />
}<br />
<br />
<br />
button_press = 0;<br />
}<br />
}<br />
}<br />
</source><br />
[[Category:U23 2008]]</div>
Hendi
https://wiki.koeln.ccc.de/index.php?title=U23_2008-2/Gruppe1&diff=14683
U23 2008-2/Gruppe1
2008-11-17T18:02:33Z
<p>Hendi: </p>
<hr />
<div>= Meta Data =<br />
== Mitglieder ==<br />
* Mark<br /><br />
* Christoph<br /><br />
* Hendrik<br /><br />
* Robert<br /><br />
<br />
= Code =<br />
== 1. Abend ==<br />
=== LED - Blinken ===<br />
: Aufgabe: Eine LED soll zum blinken gebracht werden.<br />
: Code:<br />
<source lang ="c"><br />
//****************************************************************************<br />
// * <br />
// * Von Gruppe 1<br />
// * Aufgabe: Alle LEDs sollen zum blinken gebracht werden.<br />
// * <br />
// * Task: All LED shall blink.<br />
// * <br />
//****************************************************************************<br />
<br />
#include <avr/io.h><br />
#include <util/delay.h><br />
<br />
int main(void)<br />
{<br />
/* LED Anschluss */<br />
/* LED output */<br />
/* LED1 PC4 */ <br />
/* LED2 PD3 */<br />
/* LED3 PD6 */<br />
/* LED4 PD7 */<br />
<br />
<br />
/* Setze Ports PC4, PD3, PD6 und PD7 als Ausgang */<br />
/* Set ports PC4, PD3, PD6 and PD7 as outputs */<br />
DDRC = _BV(4);<br />
DDRD = _BV(7)|_BV(6)|_BV(3);<br />
<br />
while(1)<br />
{<br />
/* _delay_ms() verzögert um 10 Millisekunden */<br />
/* 50 * 10ms = 500ms */<br />
/* _delay_ms() delays for 10 Milliseconds */<br />
/* 50 * 10ms = 500ms */<br />
for (uint8_t i=0;i<50;i++) _delay_ms(10);<br />
<br />
/* Schalte zwischen 5V und 0V an den Ausgängen hin und her */<br />
/* Toggle 5V and 0V at the outputs */<br />
PORTC ^= _BV(4);<br />
PORTD ^= _BV(7)|_BV(6)|_BV(3);<br />
}<br />
return 0;<br />
}<br />
<br />
<br />
</source><br />
<br /><br />
<br />
=== LED - Einschalten ===<br />
: Aufgabe: Eine LED soll zum leuchten gebracht werden.<br />
: Code:<br />
<source lang ="c"><br />
//****************************************************************************<br />
// * <br />
// * Von Gruppe 1<br />
// * Aufgabe: Eine LED soll zum leuchten gebracht werden.<br />
// * <br />
//****************************************************************************<br />
<br />
#include <avr/io.h><br />
<br />
int main(void)<br />
{<br />
/* PC4 auf Ausgang */<br />
DDRC = &b10000; /* Alternativ Hex: 0xF oder Dezimal: 16 */<br />
/* 7 6 5 4 3 2 1 0 */<br />
/* 0 0 0 1 0 0 0 0 */<br />
<br />
/* PC4 einschalten */<br />
PORTD = &b10000;<br />
<br />
/* Endlosschleife */<br />
while(1) <br />
{<br />
}<br />
}<br />
<br />
</source><br />
=== LED - Lauflicht ===<br />
: Code:<br />
<source lang ="c"><br />
//****************************************************************************<br />
// * <br />
// * Von Gruppe 1<br />
// * <br />
//****************************************************************************<br />
<br />
#include <avr/io.h><br />
#include <util/delay.h><br />
<br />
int main(void)<br />
{<br />
unsigned int i;<br />
<br />
/* Setze Ports PC4, PD3, PD6 und PD7 als Ausgang */<br />
DDRC = (1<<DDC4);<br />
DDRD = (1<<DDD7)|(1<<DDD6)|(1<<DDD3);<br />
/* Setze Ports PC4, PD3, PD6 und PD7 auf low */<br />
PORTC = (0<<PC4);<br />
PORTD = (0<<PD7)|(0<<PD6)|(0<<PD3);<br />
<br />
while(1)<br />
{<br />
PORTC ^= _BV(PC4);<br />
for (i=0;i<50;i++) _delay_loop_2(0);<br />
PORTC ^= _BV(PC4);<br />
PORTD ^= _BV(PD3);<br />
for (i=0;i<50;i++) _delay_loop_2(0);<br />
PORTD ^= _BV(PD3);<br />
PORTD ^= _BV(PD6);<br />
for (i=0;i<50;i++) _delay_loop_2(0);<br />
PORTD ^= _BV(PD6);<br />
PORTD ^= _BV(PD7);<br />
for (i=0;i<50;i++) _delay_loop_2(0);<br />
PORTD ^= _BV(PD7);<br />
<br />
}<br />
return 0;<br />
}<br />
</source><br />
<br />
=== Blinksequenz aufzeichnen und später abspielen ===<br />
<source lang="c">#include <avr/io.h><br />
#include <util/delay.h><br />
<br />
#define SEQS 100<br />
<br />
typedef struct {<br />
uint8_t bstate;<br />
uint32_t dur;<br />
} seq_t;<br />
<br />
seq_t seq[SEQS];<br />
uint8_t count = 0;<br />
<br />
void wait(uint32_t ms);<br />
void record(void);<br />
void play(void);<br />
<br />
void wait(uint32_t ms) {<br />
uint32_t i;<br />
<br />
for (i = 0; i < ms; i++) {<br />
_delay_ms(1);<br />
}<br />
} <br />
<br />
void record(void) {<br />
<br />
uint32_t dur = 0;<br />
uint8_t bstate_prev = 0x00; // prev button state<br />
uint8_t bstate = 0x00; // current button state<br />
<br />
while (1) {<br />
bstate = 0x00;<br />
<br />
// S1<br />
if (~PINC & _BV(PC0)) {<br />
bstate |= 1 << 1;<br />
} <br />
<br />
// S2<br />
if (~PINC & _BV(PC1)) {<br />
bstate |= 1 << 2;<br />
}<br />
<br />
// S3<br />
if (~PINC & _BV(PC2)) {<br />
bstate |= 1 << 3;<br />
}<br />
<br />
// S4<br />
if (~PINC & _BV(PC3)) {<br />
bstate |= 1 << 4;<br />
}<br />
<br />
// omit first state<br />
if (count == 0 && bstate == 0x0) {<br />
continue;<br />
}<br />
<br />
if (count >= SEQS) {<br />
// overflow error => all LEDs on<br />
while (1) {<br />
PORTC |= _BV(PC4);<br />
PORTD |= _BV(PD3) | _BV(PD6) | _BV(PD7);<br />
}<br />
}<br />
<br />
if (bstate_prev == bstate) {<br />
if (dur + 50 > dur) {<br />
dur += 50;<br />
}<br />
<br />
if (bstate == 0x0 && count > 0 && dur >= 2000) {<br />
// no button was pressed for 2s<br />
return;<br />
}<br />
} else {<br />
// save state<br />
seq[count].bstate = bstate_prev;<br />
seq[count].dur = dur;<br />
count++;<br />
<br />
// prepare for next state<br />
dur = 0;<br />
bstate_prev = bstate;<br />
}<br />
<br />
wait(50);<br />
}<br />
}<br />
<br />
void play(void) {<br />
uint8_t i;<br />
<br />
while (1) {<br />
// PORTD |= _BV(PD7);<br />
<br />
for (i = 0; i < count; i++) {<br />
// LED1<br />
if (seq[i].bstate & 1 << 1) {<br />
PORTC |= _BV(PC4);<br />
} else {<br />
PORTC &= ~_BV(PC4);<br />
}<br />
<br />
// LED2<br />
if (seq[i].bstate & 1 << 2) {<br />
PORTD |= _BV(PD3);<br />
} else {<br />
PORTD &= ~_BV(PD3);<br />
}<br />
<br />
// LED3<br />
if (seq[i].bstate & 1 << 3) {<br />
PORTD |= _BV(PD6);<br />
} else {<br />
PORTD &= ~_BV(PD6);<br />
}<br />
<br />
// LED4<br />
if (seq[i].bstate & 1 << 4) {<br />
PORTD |= _BV(PD7);<br />
} else {<br />
PORTD &= ~_BV(PD7);<br />
}<br />
<br />
wait(seq[i].dur);<br />
}<br />
<br />
PORTC &= ~_BV(PC4);<br />
PORTD &= ~_BV(PD3) & ~_BV(PD6) & ~_BV(PD7);<br />
wait(300);<br />
<br />
}<br />
}<br />
<br />
<br />
int main(void) {<br />
DDRC |= _BV(PC4);<br />
DDRD |= _BV(PD3) | _BV(PD6) | _BV(PD7); // all LEDs are output<br />
<br />
DDRC &= ~_BV(PC0) & ~_BV(PC1) & ~_BV(PC2) & ~_BV(PC3); // S[1..4] are input<br />
PORTC |= _BV(PC0) | _BV(PC1) | _BV(PC2) | _BV(PC3); // use pullup for S[1..4]<br />
<br />
// wait for pullops to "settle down"<br />
wait(1000);<br />
<br />
while (1) { <br />
record();<br />
play();<br />
}<br />
}</source><br />
<br />
== 2. Abend ==<br />
<br />
Änderungen des IR-Signals werden aufgezeichnet, und auch zeitlich ausgewertet. Messung ist jedoch relativ ungenau. Implementation von Timer / Counter fehlt.<br />
<br />
<source lang ="c"><br />
/* ################################### */<br />
/* # IR-Empfang # */<br />
/* # Von Gruppe 1 # */<br />
/* ################################### */<br />
/* # Done: IR-Signale chronologisch # */<br />
/* # aufzeichnen # */<br />
/* ################################### */<br />
/* # Todo: Counter / Timer einbauen # */<br />
/* ################################### */<br />
<br />
<br />
#include <avr/io.h><br />
#include <string.h><br />
#include <stdio.h><br />
#include <avr/pgmspace.h><br />
#include <util/delay.h><br />
#include "uart.h"<br />
<br />
int main(void)<br />
{<br />
int status = 0;<br />
int counter = 0;<br />
/* initialize serial uart */<br />
uart_init();<br />
<br />
/* configure irrx as input */<br />
DDRC &= ~_BV(PC3);<br />
<br />
/* init led pin as output */<br />
DDRD |= _BV(PD3);<br />
<br />
while(1) {<br />
counter++;<br />
for (int i = 0; i<10; i++)<br />
{<br />
_delay_us(10);<br />
}<br />
/* if ir rx is high, turn off led */<br />
if (PINC & _BV(PC3)) {<br />
// Kein IR<br />
PORTD &= ~_BV(PD3);<br />
if (status == 1)<br />
{<br />
uart_printf("Ir jetzt aus %u\n",counter);<br />
counter = 0;<br />
}<br />
status = 0;<br />
<br />
} else {<br />
PORTD |= _BV(PD3);<br />
if (status == 0)<br />
{<br />
uart_printf("Ir jetzt an %u\n",counter);<br />
counter = 0;<br />
}<br />
status = 1;<br />
}<br />
}<br />
}<br />
</source><br />
<br />
== 3. Abend ==<br />
=== IR-Jammer ===<br />
Sendet, sobald er IR empfängt, für 1000ms und wartet dann 5ms, damit er das ausgesandte Signal nicht wieder empfängt.<br />
<br />
<source lang="c"><br />
#include <avr/io.h><br />
#include <avr/interrupt.h><br />
#include <util/delay.h><br />
#include "uart.h"<br />
<br />
/* constants */<br />
#define MAX 160<br />
/* 38khz: freq = F_CPU/(2*prescaler*frequency)<br />
* 20mhz/(2*8*38khz) = ~33<br />
* real frequency: 20mhz/(2*8*33) = ~37878Hz */<br />
#define PWM_FREQ 33<br />
<br />
/* global variables */<br />
<br />
/* allocate 160*2 = 320 byte memory for storing a code,<br />
* this means we can store 80 on/off sequence timings */<br />
volatile uint16_t code[MAX];<br />
/* current index in code[] (default: 0) */<br />
volatile uint8_t pos = 0;<br />
/* current pin state (default: high == idle) */<br />
volatile uint8_t state = 1;<br />
/* signal for the main application that a code has been received<br />
* (default: 0) */<br />
volatile uint8_t done = 0;<br />
/* signal button presses from interrupt to main */<br />
volatile uint8_t button_press;<br />
/* current system mode */<br />
enum {<br />
MODE_OFF = 0,<br />
MODE_DISPLAY = 1,<br />
MODE_JAM = 2,<br />
MODE_RECORD = 3,<br />
} mode = MODE_DISPLAY;<br />
/* current viewmode */<br />
enum {<br />
VIEW_VALUE_AND_TIME = 0,<br />
VIEW_VALUE = 1,<br />
VIEW_TIME = 2,<br />
} view = VIEW_VALUE_AND_TIME;<br />
<br />
/* call every 10 ms, for buttons at pins PC0-PC3 */<br />
static uint8_t button_sample(void)<br />
{<br />
/* initialize state, buttons are active low! */<br />
static uint8_t btn_state = 15; //0b1111;<br />
/* initialize old sample */<br />
static uint8_t last_sample = 15; //0b1111;<br />
/* read inputs */<br />
uint8_t new_sample = PINC & 15; //0b1111;<br />
<br />
/* mark bits which are sampled with the same value */<br />
uint8_t same_sample = (last_sample ^ ~new_sample);<br />
/* all bits set in same_sample now have been sampled with the same value<br />
* at least two times, which means the button has settled */<br />
<br />
/* compare the current button state with the most recent sampled value,<br />
* but only for those bits which have stayed the same */<br />
uint8_t state_different = btn_state ^ (new_sample & same_sample);<br />
/* all bits set in state_different have been sampled at least two times<br />
* with the same value, and this value is different from the current<br />
* button state */<br />
<br />
/* if a bit is set in state (means: button is not pressed) AND bit is set<br />
* in state_different (means: input has settled and value is different<br />
* from state) together means: button has been pressed recently */<br />
uint8_t btn_press = btn_state & state_different;<br />
<br />
/* toggle all bits for inputs which switched state */<br />
btn_state ^= state_different;<br />
<br />
/* store current sample for next time */<br />
last_sample = new_sample;<br />
<br />
/* if bit is set in btn_press, a button has been pressed<br />
* (not released yet) */<br />
return btn_press;<br />
}<br />
<br />
void wait(uint32_t s) {<br />
uint32_t i;<br />
for (i = 0; i < s; i++) {<br />
_delay_ms(1);<br />
}<br />
}<br />
<br />
/* set up timer 0 to generate a carrier using pwm at freq on pin OC0B (PD5) */<br />
static void ir_enable(uint8_t freq) {<br />
/* timer 0: fast pwm mode, clear OC0B on match, prescaler 8 */<br />
TCCR0A = _BV(WGM00) | _BV(COM0B1);<br />
TCCR0B = _BV(CS01) | _BV(WGM02);<br />
<br />
/* set frequency */<br />
OCR0A = freq;<br />
<br />
/* set duty-cycle to 50% */<br />
OCR0B = freq/2;<br />
}<br />
<br />
/* disable timer 0 and pwm generation */<br />
static void ir_disable(void) {<br />
TCCR0A = 0;<br />
TCCR0B = 0;<br />
}<br />
<br />
<br />
/* pin change interrupt 1 service function */<br />
ISR(PCINT1_vect)<br />
{<br />
/* do nothing if we are just processing a code in the main loop,<br />
* or no more space is available for a timer value */<br />
if (done || pos == MAX)<br />
return;<br />
<br />
/* if this would be the first timing value ever recorded, and the<br />
* state before was high (=idle), do not record the timing value<br />
* and just reset the timer */<br />
if (state && pos == 0) {<br />
TCNT1 = 0;<br />
/* else record the timing value */<br />
} else {<br />
/* store current timer value in code[]<br />
* and reset the timer */<br />
code[pos++] = TCNT1;<br />
TCNT1 = 0;<br />
}<br />
<br />
/* toggle second led */<br />
PORTD ^= _BV(PD3);<br />
<br />
/* toggle state */<br />
state = !state;<br />
}<br />
<br />
/* timer 1 compare A interrupt service function */<br />
ISR(TIMER1_COMPA_vect)<br />
{<br />
/* do nothing if we are just processing a code in the main loop */<br />
if (done)<br />
return;<br />
<br />
/* if some code has been received */<br />
if (pos > 0) {<br />
/* if pos is odd, one last 'off'-timing is missing, fill with zero */<br />
if (pos % 2 == 1)<br />
code[pos++] = 0;<br />
<br />
/* signal main */<br />
done = 1;<br />
<br />
/* turn on third led */<br />
PORTD |= _BV(PD6);<br />
}<br />
}<br />
<br />
/* timer 2 compare A interrupt service function */<br />
ISR(TIMER2_COMPA_vect)<br />
{<br />
/* sample buttons every 10ms */<br />
button_press |= button_sample();<br />
}<br />
<br />
int main(void)<br />
{<br />
/* initialize uart */<br />
uart_init();<br />
uart_printf("rumpus ir analyzer\n");<br />
<br />
/* configure led pins as outputs and turn leds off */<br />
DDRC |= _BV(PC4);<br />
DDRD |= _BV(PD3) | _BV(PD6) | _BV(PD7);<br />
PORTC &= ~_BV(PC4);<br />
PORTD &= ~(_BV(PD3) | _BV(PD6) | _BV(PD7));<br />
<br />
/* configure ir input pin, with pullup */<br />
DDRC &= ~_BV(PC3);<br />
PORTC |= _BV(PC3);<br />
<br />
/* configure button input pins, with pullup */<br />
DDRC &= ~(_BV(PC0) | _BV(PC1) | _BV(PC2) | _BV(PC3));<br />
PORTC |= _BV(PC0) | _BV(PC1) | _BV(PC2) | _BV(PC3);<br />
<br />
/* configure ir send pin as output, set low */<br />
DDRD |= _BV(PD5);<br />
PORTD &= ~_BV(PD5);<br />
<br />
/* wait until pin is high (no ir carrier is detected) */<br />
while(!(PINC & _BV(PC3)));<br />
<br />
/* enable pin change interrupt 1 for ir input pin (PC3/PCINT11) */<br />
PCMSK1 |= _BV(PCINT11);<br />
PCICR |= _BV(PCIE1);<br />
<br />
/* configure timer1 with prescaler 64 and CTC for measuring ir timings */<br />
TCCR1B = _BV(CS11) | _BV(CS10) | _BV(WGM12);<br />
/* configure timer action after 200ms: 20mhz/64/5 */<br />
OCR1A = F_CPU/5/64;<br />
/* enable OCR1A interrupt */<br />
TIMSK1 = _BV(OCIE1A);<br />
<br />
/* configure timer 2 with prescaler 1024 and CTC<br />
* for button sampling */<br />
TCCR2A = _BV(WGM21);<br />
TCCR2B = _BV(CS22) | _BV(CS21) | _BV(CS20);<br />
/* configure compare event a to occur after 10ms and enable interrupt */<br />
OCR2A = F_CPU/1024/100;<br />
TIMSK2 = _BV(OCIE2A);<br />
<br />
/* signal user availability by turning on led 1 */<br />
PORTC |= _BV(PC4);<br />
<br />
/* enable interrupts */<br />
sei();<br />
<br />
/* signal the user that the analyzer part has started by turning led 1 on */<br />
PORTC |= _BV(PC3);<br />
<br />
while(1) {<br />
/* if a code has been received */<br />
if (mode == MODE_DISPLAY && done) {<br />
<br />
/* print code to serial uart */<br />
uart_printf("complete code received, %u on-off-timings:\n", pos/2);<br />
for (uint8_t i = 0; i < pos; i += 2) {<br />
<br />
if (view == VIEW_VALUE_AND_TIME) {<br />
uint32_t on, off;<br />
<br />
/* compute timing in microseconds */<br />
on = ((uint32_t)code[i]) * 64 / 20;<br />
off = ((uint32_t)code[i+1]) * 64 / 20;<br />
<br />
uart_printf(" %5lu us (%5u) on, %5lu us (%5u) off\n",<br />
on, code[i],<br />
off, code[i+1]);<br />
} else if (view == VIEW_VALUE) {<br />
uart_printf(" %5u on, %5u off\n",<br />
code[i], code[i+1]);<br />
} else if (view == VIEW_TIME) {<br />
uint32_t on, off;<br />
<br />
/* compute timing in microseconds */<br />
on = ((uint32_t)code[i]) * 64 / 20;<br />
off = ((uint32_t)code[i+1]) * 64 / 20;<br />
<br />
uart_printf(" %5lu us on, %5lu us off\n",<br />
on, off);<br />
}<br />
}<br />
<br />
<br />
/* turn off second and third led */<br />
PORTD &= ~(_BV(PD3) | _BV(PD6));<br />
<br />
/* wait until pin is high (no ir carrier is detected) */<br />
while(!(PINC & _BV(PC3)));<br />
<br />
/* reset all global variables */<br />
pos = 0;<br />
state = 1;<br />
done = 0;<br />
}<br />
<br />
if (mode == MODE_JAM) {<br />
// hier wird gejammt!<br />
<br />
if (!state) {<br />
DDRC |= _BV(PC3); // ir empfang aus<br />
<br />
ir_enable(PWM_FREQ);<br />
wait(1000);<br />
ir_disable();<br />
<br />
wait(5); // damit wir unser eben gesendetes signal nicht empfangen<br />
DDRC &= ~_BV(PC3); // ir empfang an<br />
<br />
done = 0;<br />
pos = 0;<br />
}<br />
}<br />
<br />
if (button_press) {<br />
/* first button toggles system mode */<br />
if (button_press & 1) {<br />
mode++;<br />
if (mode > MODE_RECORD)<br />
mode = MODE_OFF;<br />
<br />
if (mode == MODE_OFF) {<br />
uart_printf("ir analyzer switched off\n");<br />
<br />
/* disable timer1 and pin change interrupts */<br />
TIMSK1 &= ~_BV(OCIE1A);<br />
PCMSK1 &= ~_BV(PCINT11);<br />
<br />
/* turn off led1 */<br />
PORTC &= ~_BV(PC4);<br />
<br />
} else if (mode == MODE_DISPLAY) {<br />
uart_printf("scan and display codes\n");<br />
<br />
/* clear interrupt flags, enable timer1 and pin change interrupts */<br />
TIFR1 = _BV(OCIE1A);<br />
TIMSK1 |= _BV(OCIE1A);<br />
PCMSK1 |= _BV(PCINT11);<br />
<br />
/* turn on led1 */<br />
PORTC |= _BV(PC4);<br />
} else if (mode == MODE_JAM) {<br />
/* clear interrupt flags, enable timer1 and pin change interrupts */<br />
TIFR1 = _BV(OCIE1A);<br />
TIMSK1 |= _BV(OCIE1A);<br />
PCMSK1 |= _BV(PCINT11);<br />
<br />
uart_printf("jamming mode active\n");<br />
} else if (mode == MODE_RECORD) {<br />
uart_printf("record and replay a code\n");<br />
}<br />
}<br />
<br />
<br />
/* second button toggles view mode */<br />
if (button_press & 2) {<br />
view++;<br />
if (view > VIEW_TIME)<br />
view = VIEW_VALUE_AND_TIME;<br />
<br />
if (view == VIEW_VALUE_AND_TIME)<br />
uart_printf("display timer value and time (in us)\n");<br />
else if (view == VIEW_VALUE)<br />
uart_printf("display timer value\n");<br />
else if (view == VIEW_TIME)<br />
uart_printf("display time (in us)\n");<br />
}<br />
<br />
if (button_press & 4) {<br />
static uint8_t pwm = 0;<br />
<br />
if (!pwm) {<br />
ir_enable(PWM_FREQ);<br />
uart_printf("pwm on\n");<br />
} else {<br />
ir_disable();<br />
uart_printf("pwm off\n");<br />
}<br />
pwm = !pwm;<br />
}<br />
<br />
button_press = 0;<br />
}<br />
}<br />
}</source><br />
<br />
== 4. Abend ==<br />
=== IR-Jammer in schlau ===<br />
Misst die kürzeste Impulsdauer und sendet mit dieser (plus einer kleinen, sich ändernden Verzögerung) in die Pausen.<br />
<br />
<source lang="c">#include <avr/io.h><br />
#include <avr/interrupt.h><br />
#include <util/delay.h><br />
#include "uart.h"<br />
<br />
/* constants */<br />
#define MAX 160<br />
/* 38khz: freq = F_CPU/(2*prescaler*frequency)<br />
* 20mhz/(2*8*38khz) = ~33<br />
* real frequency: 20mhz/(2*8*33) = ~37878Hz */<br />
#define PWM_FREQ 33<br />
<br />
/* global variables */<br />
<br />
/* allocate 160*2 = 320 byte memory for storing a code,<br />
* this means we can store 80 on/off sequence timings */<br />
volatile uint16_t code[MAX];<br />
/* current index in code[] (default: 0) */<br />
volatile uint8_t pos = 0;<br />
/* current pin state (default: high == idle) */<br />
volatile uint8_t state = 1;<br />
/* signal for the main application that a code has been received<br />
* (default: 0) */<br />
volatile uint8_t done = 0;<br />
/* signal button presses from interrupt to main */<br />
volatile uint8_t button_press;<br />
/* current system mode */<br />
enum {<br />
MODE_OFF = 0,<br />
MODE_DISPLAY = 1,<br />
MODE_JAM = 2,<br />
MODE_RECORD = 3,<br />
} mode = MODE_DISPLAY;<br />
/* current viewmode */<br />
enum {<br />
VIEW_VALUE_AND_TIME = 0,<br />
VIEW_VALUE = 1,<br />
VIEW_TIME = 2,<br />
} view = VIEW_VALUE_AND_TIME;<br />
<br />
/* call every 10 ms, for buttons at pins PC0-PC3 */<br />
static uint8_t button_sample(void)<br />
{<br />
/* initialize state, buttons are active low! */<br />
static uint8_t btn_state = 15; //0b1111;<br />
/* initialize old sample */<br />
static uint8_t last_sample = 15; //0b1111;<br />
/* read inputs */<br />
uint8_t new_sample = PINC & 15; //0b1111;<br />
<br />
/* mark bits which are sampled with the same value */<br />
uint8_t same_sample = (last_sample ^ ~new_sample);<br />
/* all bits set in same_sample now have been sampled with the same value<br />
* at least two times, which means the button has settled */<br />
<br />
/* compare the current button state with the most recent sampled value,<br />
* but only for those bits which have stayed the same */<br />
uint8_t state_different = btn_state ^ (new_sample & same_sample);<br />
/* all bits set in state_different have been sampled at least two times<br />
* with the same value, and this value is different from the current<br />
* button state */<br />
<br />
/* if a bit is set in state (means: button is not pressed) AND bit is set<br />
* in state_different (means: input has settled and value is different<br />
* from state) together means: button has been pressed recently */<br />
uint8_t btn_press = btn_state & state_different;<br />
<br />
/* toggle all bits for inputs which switched state */<br />
btn_state ^= state_different;<br />
<br />
/* store current sample for next time */<br />
last_sample = new_sample;<br />
<br />
/* if bit is set in btn_press, a button has been pressed<br />
* (not released yet) */<br />
return btn_press;<br />
}<br />
<br />
static void wait(uint32_t s) {<br />
uint32_t i;<br />
for (i = 0; i < s; i++) {<br />
_delay_us(1);<br />
}<br />
}<br />
<br />
/* set up timer 0 to generate a carrier using pwm at freq on pin OC0B (PD5) */<br />
static void ir_enable(uint8_t freq) {<br />
/* timer 0: fast pwm mode, clear OC0B on match, prescaler 8 */<br />
TCCR0A = _BV(WGM00) | _BV(COM0B1);<br />
TCCR0B = _BV(CS01) | _BV(WGM02);<br />
<br />
/* set frequency */<br />
OCR0A = freq;<br />
<br />
/* set duty-cycle to 50% */<br />
OCR0B = freq/2;<br />
}<br />
<br />
/* disable timer 0 and pwm generation */<br />
static void ir_disable(void) {<br />
TCCR0A = 0;<br />
TCCR0B = 0;<br />
}<br />
<br />
static void jam(void) {<br />
static uint32_t dur;<br />
static uint16_t i;<br />
uint8_t j = 0;<br />
uint32_t dur_tmp;<br />
<br />
if (pos == 0 || done) {<br />
dur = 0xFFFFFFFF;<br />
}<br />
<br />
if (i % 500 == 0) {<br />
i=0;<br />
if (!state) {<br />
uart_printf("-");<br />
} else {<br />
uart_printf(".");<br />
}<br />
}<br />
i++;<br />
<br />
<br />
if (pos < 1) {<br />
return;<br />
}<br />
<br />
// shortest measured duration<br />
dur_tmp = ((uint32_t)code[pos-1]) * 64 / 20;<br />
dur = dur_tmp < dur ? dur_tmp : dur;<br />
<br />
while (!state && j < 10) {<br />
j++;<br />
DDRC |= _BV(PC3); // ir reciever off<br />
<br />
ir_enable(PWM_FREQ);<br />
uart_printf("*");<br />
wait(dur+i);<br />
ir_disable();<br />
<br />
wait(250); // we don't want to recieve our own signal (due to lags in the ir receiver)<br />
DDRC &= ~_BV(PC3); // ir reciever on<br />
}<br />
}<br />
<br />
/* pin change interrupt 1 service function */<br />
ISR(PCINT1_vect)<br />
{<br />
/* do nothing if we are just processing a code in the main loop,<br />
* or no more space is available for a timer value */<br />
if (done || pos == MAX)<br />
return;<br />
<br />
/* if this would be the first timing value ever recorded, and the<br />
* state before was high (=idle), do not record the timing value<br />
* and just reset the timer */<br />
if (state && pos == 0) {<br />
TCNT1 = 0;<br />
/* else record the timing value */<br />
} else {<br />
/* store current timer value in code[]<br />
* and reset the timer */<br />
code[pos++] = TCNT1;<br />
TCNT1 = 0;<br />
}<br />
<br />
/* toggle second led */<br />
PORTD ^= _BV(PD3);<br />
<br />
/* toggle state */<br />
state = !state;<br />
}<br />
<br />
/* timer 1 compare A interrupt service function */<br />
ISR(TIMER1_COMPA_vect)<br />
{<br />
/* do nothing if we are just processing a code in the main loop */<br />
if (done)<br />
return;<br />
<br />
/* if some code has been received */<br />
if (pos > 0) {<br />
/* if pos is odd, one last 'off'-timing is missing, fill with zero */<br />
if (pos % 2 == 1)<br />
code[pos++] = 0;<br />
<br />
/* signal main */<br />
done = 1;<br />
<br />
/* turn on third led */<br />
PORTD |= _BV(PD6);<br />
}<br />
}<br />
<br />
/* timer 2 compare A interrupt service function */<br />
ISR(TIMER2_COMPA_vect)<br />
{<br />
/* sample buttons every 10ms */<br />
button_press |= button_sample();<br />
}<br />
<br />
int main(void)<br />
{<br />
/* initialize uart */<br />
uart_init();<br />
uart_printf("rumpus ir analyzer\n");<br />
<br />
/* configure led pins as outputs and turn leds off */<br />
DDRC |= _BV(PC4);<br />
DDRD |= _BV(PD3) | _BV(PD6) | _BV(PD7);<br />
PORTC &= ~_BV(PC4);<br />
PORTD &= ~(_BV(PD3) | _BV(PD6) | _BV(PD7));<br />
<br />
/* configure ir input pin, with pullup */<br />
DDRC &= ~_BV(PC3);<br />
PORTC |= _BV(PC3);<br />
<br />
/* configure button input pins, with pullup */<br />
DDRC &= ~(_BV(PC0) | _BV(PC1) | _BV(PC2) | _BV(PC3));<br />
PORTC |= _BV(PC0) | _BV(PC1) | _BV(PC2) | _BV(PC3);<br />
<br />
/* configure ir send pin as output, set low */<br />
DDRD |= _BV(PD5);<br />
PORTD &= ~_BV(PD5);<br />
<br />
/* wait until pin is high (no ir carrier is detected) */<br />
while(!(PINC & _BV(PC3)));<br />
<br />
/* enable pin change interrupt 1 for ir input pin (PC3/PCINT11) */<br />
PCMSK1 |= _BV(PCINT11);<br />
PCICR |= _BV(PCIE1);<br />
<br />
/* configure timer1 with prescaler 64 and CTC for measuring ir timings */<br />
TCCR1B = _BV(CS11) | _BV(CS10) | _BV(WGM12);<br />
/* configure timer action after 200ms: 20mhz/64/5 */<br />
OCR1A = F_CPU/5/64;<br />
/* enable OCR1A interrupt */<br />
TIMSK1 = _BV(OCIE1A);<br />
<br />
/* configure timer 2 with prescaler 1024 and CTC<br />
* for button sampling */<br />
TCCR2A = _BV(WGM21);<br />
TCCR2B = _BV(CS22) | _BV(CS21) | _BV(CS20);<br />
/* configure compare event a to occur after 10ms and enable interrupt */<br />
OCR2A = F_CPU/1024/100;<br />
TIMSK2 = _BV(OCIE2A);<br />
<br />
/* signal user availability by turning on led 1 */<br />
PORTC |= _BV(PC4);<br />
<br />
/* enable interrupts */<br />
sei();<br />
<br />
/* signal the user that the analyzer part has started by turning led 1 on */<br />
PORTC |= _BV(PC3);<br />
<br />
while(1) {<br />
/* if a code has been received */<br />
if (mode == MODE_DISPLAY && done) {<br />
<br />
/* print code to serial uart */<br />
uart_printf("complete code received, %u on-off-timings:\n", pos/2);<br />
for (uint8_t i = 0; i < pos; i += 2) {<br />
<br />
if (view == VIEW_VALUE_AND_TIME) {<br />
uint32_t on, off;<br />
<br />
/* compute timing in microseconds */<br />
on = ((uint32_t)code[i]) * 64 / 20;<br />
off = ((uint32_t)code[i+1]) * 64 / 20;<br />
<br />
uart_printf(" %5lu us (%5u) on, %5lu us (%5u) off\n",<br />
on, code[i],<br />
off, code[i+1]);<br />
} else if (view == VIEW_VALUE) {<br />
uart_printf(" %5u on, %5u off\n",<br />
code[i], code[i+1]);<br />
} else if (view == VIEW_TIME) {<br />
uint32_t on, off;<br />
<br />
/* compute timing in microseconds */<br />
on = ((uint32_t)code[i]) * 64 / 20;<br />
off = ((uint32_t)code[i+1]) * 64 / 20;<br />
<br />
uart_printf(" %5lu us on, %5lu us off\n",<br />
on, off);<br />
}<br />
}<br />
<br />
<br />
/* turn off second and third led */<br />
PORTD &= ~(_BV(PD3) | _BV(PD6));<br />
<br />
/* wait until pin is high (no ir carrier is detected) */<br />
while(!(PINC & _BV(PC3)));<br />
<br />
/* reset all global variables */<br />
pos = 0;<br />
state = 1;<br />
done = 0;<br />
}<br />
<br />
if (mode == MODE_JAM) {<br />
jam();<br />
}<br />
<br />
if (done) {<br />
// code completely detected<br />
<br />
/* reset all global variables */<br />
pos = 0;<br />
state = 1;<br />
done = 0;<br />
} <br />
<br />
if (button_press) {<br />
/* first button toggles system mode */<br />
if (button_press & 1) {<br />
mode++;<br />
if (mode > MODE_RECORD)<br />
mode = MODE_OFF;<br />
<br />
if (mode == MODE_OFF) {<br />
uart_printf("ir analyzer switched off\n");<br />
<br />
/* disable timer1 and pin change interrupts */<br />
TIMSK1 &= ~_BV(OCIE1A);<br />
PCMSK1 &= ~_BV(PCINT11);<br />
<br />
/* turn off led1 */<br />
PORTC &= ~_BV(PC4);<br />
<br />
} else if (mode == MODE_DISPLAY) {<br />
uart_printf("scan and display codes\n");<br />
<br />
/* clear interrupt flags, enable timer1 and pin change interrupts */<br />
TIFR1 = _BV(OCIE1A);<br />
TIMSK1 |= _BV(OCIE1A);<br />
PCMSK1 |= _BV(PCINT11);<br />
<br />
/* turn on led1 */<br />
PORTC |= _BV(PC4);<br />
} else if (mode == MODE_JAM) {<br />
/* clear interrupt flags, enable timer1 and pin change interrupts */<br />
TIFR1 = _BV(OCIE1A);<br />
TIMSK1 |= _BV(OCIE1A);<br />
PCMSK1 |= _BV(PCINT11);<br />
<br />
uart_printf("jamming mode active\n");<br />
} else if (mode == MODE_RECORD) {<br />
uart_printf("record and replay a code\n");<br />
}<br />
}<br />
<br />
<br />
/* second button toggles view mode */<br />
if (button_press & 2) {<br />
view++;<br />
if (view > VIEW_TIME)<br />
view = VIEW_VALUE_AND_TIME;<br />
<br />
if (view == VIEW_VALUE_AND_TIME)<br />
uart_printf("display timer value and time (in us)\n");<br />
else if (view == VIEW_VALUE)<br />
uart_printf("display timer value\n");<br />
else if (view == VIEW_TIME)<br />
uart_printf("display time (in us)\n");<br />
}<br />
<br />
if (button_press & 4) {<br />
static uint8_t pwm = 0;<br />
<br />
if (!pwm) {<br />
ir_enable(PWM_FREQ);<br />
uart_printf("pwm on\n");<br />
} else {<br />
ir_disable();<br />
uart_printf("pwm off\n");<br />
}<br />
pwm = !pwm;<br />
}<br />
<br />
button_press = 0;<br />
}<br />
}<br />
}</source><br />
<br />
=== Eigener Chat (Test) ===<br />
<source lang="c">#include <avr/io.h><br />
#include <avr/interrupt.h><br />
#include <util/delay.h><br />
#include "uart.h"<br />
<br />
/* constants */<br />
#define MAX 160<br />
/* 38khz: freq = F_CPU/(2*prescaler*frequency)<br />
* 20mhz/(2*8*38khz) = ~33<br />
* real frequency: 20mhz/(2*8*33) = ~37878Hz */<br />
#define PWM_FREQ 33<br />
<br />
/* global variables */<br />
<br />
/* allocate 160*2 = 320 byte memory for storing a code,<br />
* this means we can store 80 on/off sequence timings */<br />
volatile uint16_t code[MAX];<br />
/* current index in code[] (default: 0) */<br />
volatile uint8_t pos = 0;<br />
/* current pin state (default: high == idle) */<br />
volatile uint8_t state = 1;<br />
/* signal for the main application that a code has been received<br />
* (default: 0) */<br />
volatile uint8_t done = 0;<br />
/* signal button presses from interrupt to main */<br />
volatile uint8_t button_press;<br />
/* current system mode */<br />
enum {<br />
MODE_OFF = 0,<br />
MODE_DISPLAY = 1,<br />
MODE_JAM = 2,<br />
MODE_RECORD = 3,<br />
} mode = MODE_DISPLAY;<br />
/* current viewmode */<br />
enum {<br />
VIEW_VALUE_AND_TIME = 0,<br />
VIEW_VALUE = 1,<br />
VIEW_TIME = 2,<br />
} view = VIEW_VALUE_AND_TIME;<br />
<br />
/* call every 10 ms, for buttons at pins PC0-PC3 */<br />
static uint8_t button_sample(void)<br />
{<br />
/* initialize state, buttons are active low! */<br />
static uint8_t btn_state = 15; //0b1111;<br />
/* initialize old sample */<br />
static uint8_t last_sample = 15; //0b1111;<br />
/* read inputs */<br />
uint8_t new_sample = PINC & 15; //0b1111;<br />
<br />
/* mark bits which are sampled with the same value */<br />
uint8_t same_sample = (last_sample ^ ~new_sample);<br />
/* all bits set in same_sample now have been sampled with the same value<br />
* at least two times, which means the button has settled */<br />
<br />
/* compare the current button state with the most recent sampled value,<br />
* but only for those bits which have stayed the same */<br />
uint8_t state_different = btn_state ^ (new_sample & same_sample);<br />
/* all bits set in state_different have been sampled at least two times<br />
* with the same value, and this value is different from the current<br />
* button state */<br />
<br />
/* if a bit is set in state (means: button is not pressed) AND bit is set<br />
* in state_different (means: input has settled and value is different<br />
* from state) together means: button has been pressed recently */<br />
uint8_t btn_press = btn_state & state_different;<br />
<br />
/* toggle all bits for inputs which switched state */<br />
btn_state ^= state_different;<br />
<br />
/* store current sample for next time */<br />
last_sample = new_sample;<br />
<br />
/* if bit is set in btn_press, a button has been pressed<br />
* (not released yet) */<br />
return btn_press;<br />
}<br />
<br />
static void wait(uint32_t s) {<br />
uint32_t i;<br />
s /= 100;<br />
for (i = 0; i < s; i++) {<br />
_delay_us(100);<br />
}<br />
}<br />
<br />
/* set up timer 0 to generate a carrier using pwm at freq on pin OC0B (PD5) */<br />
static void ir_enable(uint8_t freq) {<br />
/* timer 0: fast pwm mode, clear OC0B on match, prescaler 8 */<br />
TCCR0A = _BV(WGM00) | _BV(COM0B1);<br />
TCCR0B = _BV(CS01) | _BV(WGM02);<br />
<br />
/* set frequency */<br />
OCR0A = freq;<br />
<br />
/* set duty-cycle to 1/4 */<br />
OCR0B = freq/4;<br />
}<br />
<br />
/* disable timer 0 and pwm generation */<br />
static void ir_disable(void) {<br />
TCCR0A = 0;<br />
TCCR0B = 0;<br />
}<br />
<br />
<br />
/* pin change interrupt 1 service function */<br />
ISR(PCINT1_vect)<br />
{<br />
/* do nothing if we are just processing a code in the main loop,<br />
* or no more space is available for a timer value */<br />
if (done || pos == MAX)<br />
return;<br />
<br />
/* if this would be the first timing value ever recorded, and the<br />
* state before was high (=idle), do not record the timing value<br />
* and just reset the timer */<br />
if (state && pos == 0) {<br />
TCNT1 = 0;<br />
/* else record the timing value */<br />
} else {<br />
/* store current timer value in code[]<br />
* and reset the timer */<br />
code[pos++] = TCNT1;<br />
TCNT1 = 0;<br />
}<br />
<br />
/* toggle second led */<br />
PORTD ^= _BV(PD3);<br />
<br />
/* toggle state */<br />
state = !state;<br />
}<br />
<br />
/* timer 1 compare A interrupt service function */<br />
ISR(TIMER1_COMPA_vect)<br />
{<br />
/* do nothing if we are just processing a code in the main loop */<br />
if (done)<br />
return;<br />
<br />
/* if some code has been received */<br />
if (pos > 0) {<br />
/* if pos is odd, one last 'off'-timing is missing, fill with zero */<br />
if (pos % 2 == 1)<br />
code[pos++] = 0;<br />
<br />
/* signal main */<br />
done = 1;<br />
<br />
/* turn on third led */<br />
PORTD |= _BV(PD6);<br />
}<br />
}<br />
<br />
/* timer 2 compare A interrupt service function */<br />
ISR(TIMER2_COMPA_vect)<br />
{<br />
/* sample buttons every 10ms */<br />
button_press |= button_sample();<br />
}<br />
<br />
// NEC protocol, see http://www.sbprojects.com/knowledge/ir/nec.htm<br />
static void send1() {<br />
// uart_printf("1");<br />
ir_enable(PWM_FREQ);<br />
wait(560);<br />
ir_disable();<br />
wait(560);<br />
wait(560);<br />
}<br />
<br />
static void send0() {<br />
// uart_printf("0");<br />
ir_enable(PWM_FREQ);<br />
wait(560);<br />
ir_disable();<br />
wait(560);<br />
}<br />
<br />
static void send(uint8_t sendcode) {<br />
// say hello<br />
ir_enable(PWM_FREQ);<br />
wait(9000);<br />
ir_disable();<br />
wait(4500);<br />
<br />
// send data<br />
for (uint8_t i=0; i<8; i++) {<br />
if (sendcode & (1 << i)) {<br />
send1();<br />
} else {<br />
send0();<br />
}<br />
}<br />
<br />
// send ~data as verification<br />
for (uint8_t i=0; i<8; i++) {<br />
if (~sendcode & (1 << i)) {<br />
send1();<br />
} else {<br />
send0();<br />
}<br />
}<br />
<br />
// enable IR, so we know how long it was off<br />
ir_enable(PWM_FREQ);<br />
wait(560);<br />
ir_disable();<br />
<br />
uart_printf("\n");<br />
<br />
}<br />
<br />
static uint8_t receive(void) {<br />
uint8_t rcv[2];<br />
uint8_t fail = 0;<br />
<br />
// transform time to ms<br />
for (uint8_t i = 0; i < pos; i++) {<br />
code[i] *= 64 / 20 * 2.75;<br />
}<br />
<br />
// receive hello<br />
if (code[0] < 8500 || code[0] > 9500<br />
|| code[1] < 4000 || code[1] > 5000<br />
|| pos < 34<br />
) {<br />
// no nec hello found<br />
return (uint8_t)'_';<br />
}<br />
<br />
// receive msg<br />
for (uint8_t j=0; j<2; j++) {<br />
for (uint8_t i=0; i<8; i++) {<br />
//uart_printf("%d - ", code[16*j + 2*i + 2]);<br />
//uart_printf("%d", code[16*j + 2*i + 3]);<br />
<br />
if (!(code[16*j + 2*i + 2] > 400 && code[16*j + 2*i + 2] < 800)) {<br />
// bit doesn't start with ON<br />
fail |= 1 << j;<br />
uart_printf(" off FAIL (%d)\n", code[16*j + 2*i +2]);<br />
<br />
i=8; continue; // go to next byte<br />
}<br />
<br />
if (code[16*j + 2*i + 3] > 400 && code[16*j + 2*i + 3] < 800) {<br />
// bit is 0<br />
rcv[j] &= ~(1 << i);<br />
} else if (code[16*j + 2*i + 3] > 900 && code[16*j + 2*i + 3] < 1300) {<br />
// bit is 1<br />
rcv[j] |= 1 << i;<br />
} else {<br />
// not sure which value we have<br />
fail |= 1 << j;<br />
uart_printf(" FAIL (%d)\n", code[16*j + 2*i + 3]);<br />
<br />
i=8; continue; // go to next byte<br />
}<br />
uart_printf("\n");<br />
}<br />
}<br />
<br />
// check for errors<br />
rcv[1] = ~rcv[1];<br />
// msg[3] = ~msg[3];<br />
<br />
if (<br />
~((fail & (1 << 0)) | (fail & (1 << 1)))<br />
&& rcv[0] == rcv[1]<br />
) {<br />
return rcv[0];<br />
}<br />
<br />
<br />
uart_printf("%d\n%d\n", rcv[0], rcv[1]);<br />
return (uint8_t)'?';<br />
}<br />
<br />
int main(void)<br />
{<br />
/* initialize uart */<br />
uart_init();<br />
uart_printf("rumpus ir chat\n");<br />
<br />
/* configure led pins as outputs and turn leds off */<br />
DDRC |= _BV(PC4);<br />
DDRD |= _BV(PD3) | _BV(PD6) | _BV(PD7);<br />
PORTC &= ~_BV(PC4);<br />
PORTD &= ~(_BV(PD3) | _BV(PD6) | _BV(PD7));<br />
<br />
/* configure ir input pin, with pullup */<br />
DDRC &= ~_BV(PC3);<br />
PORTC |= _BV(PC3);<br />
<br />
/* configure button input pins, with pullup */<br />
DDRC &= ~(_BV(PC0) | _BV(PC1) | _BV(PC2) | _BV(PC3));<br />
PORTC |= _BV(PC0) | _BV(PC1) | _BV(PC2) | _BV(PC3);<br />
<br />
/* configure ir send pin as output, set low */<br />
DDRD |= _BV(PD5);<br />
PORTD &= ~_BV(PD5);<br />
<br />
/* wait until pin is high (no ir carrier is detected) */<br />
while(!(PINC & _BV(PC3)));<br />
<br />
/* enable pin change interrupt 1 for ir input pin (PC3/PCINT11) */<br />
PCMSK1 |= _BV(PCINT11);<br />
PCICR |= _BV(PCIE1);<br />
<br />
/* configure timer1 with prescaler 64 and CTC for measuring ir timings */<br />
TCCR1B = _BV(CS11) | _BV(CS10) | _BV(WGM12);<br />
/* configure timer action after 200ms: 20mhz/64/5 */<br />
OCR1A = F_CPU/5/64;<br />
/* enable OCR1A interrupt */<br />
TIMSK1 = _BV(OCIE1A);<br />
<br />
/* configure timer 2 with prescaler 1024 and CTC<br />
* for button sampling */<br />
TCCR2A = _BV(WGM21);<br />
TCCR2B = _BV(CS22) | _BV(CS21) | _BV(CS20);<br />
/* configure compare event a to occur after 10ms and enable interrupt */<br />
OCR2A = F_CPU/1024/100;<br />
TIMSK2 = _BV(OCIE2A);<br />
<br />
/* signal user availability by turning on led 1 */<br />
PORTC |= _BV(PC4);<br />
<br />
/* enable interrupts */<br />
sei();<br />
<br />
/* signal the user that the analyzer part has started by turning led 1 on */<br />
PORTC |= _BV(PC3);<br />
<br />
while(1) {<br />
<br />
/* if a code has been received */<br />
if (done) {<br />
uart_printf("Received: %c\n", receive());<br />
<br />
/* turn off second and third led */<br />
PORTD &= ~(_BV(PD3) | _BV(PD6));<br />
<br />
/* wait until pin is high (no ir carrier is detected) */<br />
while(!(PINC & _BV(PC3)));<br />
<br />
/* reset all global variables */<br />
pos = 0;<br />
state = 1;<br />
done = 0;<br />
}<br />
<br />
<br />
if (button_press) {<br />
/* first button toggles system mode */<br />
if (button_press) {<br />
// SENDEN<br />
if (button_press & (1 << 0)) {<br />
send((uint8_t)'U');<br />
} else if (button_press & (1 << 1)) {<br />
send((uint8_t)('2')); // 0b101<br />
} else if (button_press & (1 << 2)) {<br />
send((uint8_t)('3')); // 0b10001<br />
}<br />
}<br />
<br />
button_press = 0;<br />
}<br />
}<br />
}</source><br />
[[Category:U23 2008]]</div>
Hendi
https://wiki.koeln.ccc.de/index.php?title=U23_2008-2/Gruppe1&diff=14680
U23 2008-2/Gruppe1
2008-11-11T09:30:20Z
<p>Hendi: </p>
<hr />
<div>= Meta Data =<br />
== Mitglieder ==<br />
* Mark<br /><br />
* Christoph<br /><br />
* Hendrik<br /><br />
* Robert<br /><br />
<br />
= Code =<br />
== 1. Abend ==<br />
=== LED - Blinken ===<br />
: Aufgabe: Eine LED soll zum blinken gebracht werden.<br />
: Code:<br />
<source lang ="c"><br />
//****************************************************************************<br />
// * <br />
// * Von Gruppe 1<br />
// * Aufgabe: Alle LEDs sollen zum blinken gebracht werden.<br />
// * <br />
// * Task: All LED shall blink.<br />
// * <br />
//****************************************************************************<br />
<br />
#include <avr/io.h><br />
#include <util/delay.h><br />
<br />
int main(void)<br />
{<br />
/* LED Anschluss */<br />
/* LED output */<br />
/* LED1 PC4 */ <br />
/* LED2 PD3 */<br />
/* LED3 PD6 */<br />
/* LED4 PD7 */<br />
<br />
<br />
/* Setze Ports PC4, PD3, PD6 und PD7 als Ausgang */<br />
/* Set ports PC4, PD3, PD6 and PD7 as outputs */<br />
DDRC = _BV(4);<br />
DDRD = _BV(7)|_BV(6)|_BV(3);<br />
<br />
while(1)<br />
{<br />
/* _delay_ms() verzögert um 10 Millisekunden */<br />
/* 50 * 10ms = 500ms */<br />
/* _delay_ms() delays for 10 Milliseconds */<br />
/* 50 * 10ms = 500ms */<br />
for (uint8_t i=0;i<50;i++) _delay_ms(10);<br />
<br />
/* Schalte zwischen 5V und 0V an den Ausgängen hin und her */<br />
/* Toggle 5V and 0V at the outputs */<br />
PORTC ^= _BV(4);<br />
PORTD ^= _BV(7)|_BV(6)|_BV(3);<br />
}<br />
return 0;<br />
}<br />
<br />
<br />
</source><br />
<br /><br />
<br />
=== LED - Einschalten ===<br />
: Aufgabe: Eine LED soll zum leuchten gebracht werden.<br />
: Code:<br />
<source lang ="c"><br />
//****************************************************************************<br />
// * <br />
// * Von Gruppe 1<br />
// * Aufgabe: Eine LED soll zum leuchten gebracht werden.<br />
// * <br />
//****************************************************************************<br />
<br />
#include <avr/io.h><br />
<br />
int main(void)<br />
{<br />
/* PC4 auf Ausgang */<br />
DDRC = &b10000; /* Alternativ Hex: 0xF oder Dezimal: 16 */<br />
/* 7 6 5 4 3 2 1 0 */<br />
/* 0 0 0 1 0 0 0 0 */<br />
<br />
/* PC4 einschalten */<br />
PORTD = &b10000;<br />
<br />
/* Endlosschleife */<br />
while(1) <br />
{<br />
}<br />
}<br />
<br />
</source><br />
=== LED - Lauflicht ===<br />
: Code:<br />
<source lang ="c"><br />
//****************************************************************************<br />
// * <br />
// * Von Gruppe 1<br />
// * <br />
//****************************************************************************<br />
<br />
#include <avr/io.h><br />
#include <util/delay.h><br />
<br />
int main(void)<br />
{<br />
unsigned int i;<br />
<br />
/* Setze Ports PC4, PD3, PD6 und PD7 als Ausgang */<br />
DDRC = (1<<DDC4);<br />
DDRD = (1<<DDD7)|(1<<DDD6)|(1<<DDD3);<br />
/* Setze Ports PC4, PD3, PD6 und PD7 auf low */<br />
PORTC = (0<<PC4);<br />
PORTD = (0<<PD7)|(0<<PD6)|(0<<PD3);<br />
<br />
while(1)<br />
{<br />
PORTC ^= _BV(PC4);<br />
for (i=0;i<50;i++) _delay_loop_2(0);<br />
PORTC ^= _BV(PC4);<br />
PORTD ^= _BV(PD3);<br />
for (i=0;i<50;i++) _delay_loop_2(0);<br />
PORTD ^= _BV(PD3);<br />
PORTD ^= _BV(PD6);<br />
for (i=0;i<50;i++) _delay_loop_2(0);<br />
PORTD ^= _BV(PD6);<br />
PORTD ^= _BV(PD7);<br />
for (i=0;i<50;i++) _delay_loop_2(0);<br />
PORTD ^= _BV(PD7);<br />
<br />
}<br />
return 0;<br />
}<br />
</source><br />
<br />
=== Blinksequenz aufzeichnen und später abspielen ===<br />
<source lang="c">#include <avr/io.h><br />
#include <util/delay.h><br />
<br />
#define SEQS 100<br />
<br />
typedef struct {<br />
uint8_t bstate;<br />
uint32_t dur;<br />
} seq_t;<br />
<br />
seq_t seq[SEQS];<br />
uint8_t count = 0;<br />
<br />
void wait(uint32_t ms);<br />
void record(void);<br />
void play(void);<br />
<br />
void wait(uint32_t ms) {<br />
uint32_t i;<br />
<br />
for (i = 0; i < ms; i++) {<br />
_delay_ms(1);<br />
}<br />
} <br />
<br />
void record(void) {<br />
<br />
uint32_t dur = 0;<br />
uint8_t bstate_prev = 0x00; // prev button state<br />
uint8_t bstate = 0x00; // current button state<br />
<br />
while (1) {<br />
bstate = 0x00;<br />
<br />
// S1<br />
if (~PINC & _BV(PC0)) {<br />
bstate |= 1 << 1;<br />
} <br />
<br />
// S2<br />
if (~PINC & _BV(PC1)) {<br />
bstate |= 1 << 2;<br />
}<br />
<br />
// S3<br />
if (~PINC & _BV(PC2)) {<br />
bstate |= 1 << 3;<br />
}<br />
<br />
// S4<br />
if (~PINC & _BV(PC3)) {<br />
bstate |= 1 << 4;<br />
}<br />
<br />
// omit first state<br />
if (count == 0 && bstate == 0x0) {<br />
continue;<br />
}<br />
<br />
if (count >= SEQS) {<br />
// overflow error => all LEDs on<br />
while (1) {<br />
PORTC |= _BV(PC4);<br />
PORTD |= _BV(PD3) | _BV(PD6) | _BV(PD7);<br />
}<br />
}<br />
<br />
if (bstate_prev == bstate) {<br />
if (dur + 50 > dur) {<br />
dur += 50;<br />
}<br />
<br />
if (bstate == 0x0 && count > 0 && dur >= 2000) {<br />
// no button was pressed for 2s<br />
return;<br />
}<br />
} else {<br />
// save state<br />
seq[count].bstate = bstate_prev;<br />
seq[count].dur = dur;<br />
count++;<br />
<br />
// prepare for next state<br />
dur = 0;<br />
bstate_prev = bstate;<br />
}<br />
<br />
wait(50);<br />
}<br />
}<br />
<br />
void play(void) {<br />
uint8_t i;<br />
<br />
while (1) {<br />
// PORTD |= _BV(PD7);<br />
<br />
for (i = 0; i < count; i++) {<br />
// LED1<br />
if (seq[i].bstate & 1 << 1) {<br />
PORTC |= _BV(PC4);<br />
} else {<br />
PORTC &= ~_BV(PC4);<br />
}<br />
<br />
// LED2<br />
if (seq[i].bstate & 1 << 2) {<br />
PORTD |= _BV(PD3);<br />
} else {<br />
PORTD &= ~_BV(PD3);<br />
}<br />
<br />
// LED3<br />
if (seq[i].bstate & 1 << 3) {<br />
PORTD |= _BV(PD6);<br />
} else {<br />
PORTD &= ~_BV(PD6);<br />
}<br />
<br />
// LED4<br />
if (seq[i].bstate & 1 << 4) {<br />
PORTD |= _BV(PD7);<br />
} else {<br />
PORTD &= ~_BV(PD7);<br />
}<br />
<br />
wait(seq[i].dur);<br />
}<br />
<br />
PORTC &= ~_BV(PC4);<br />
PORTD &= ~_BV(PD3) & ~_BV(PD6) & ~_BV(PD7);<br />
wait(300);<br />
<br />
}<br />
}<br />
<br />
<br />
int main(void) {<br />
DDRC |= _BV(PC4);<br />
DDRD |= _BV(PD3) | _BV(PD6) | _BV(PD7); // all LEDs are output<br />
<br />
DDRC &= ~_BV(PC0) & ~_BV(PC1) & ~_BV(PC2) & ~_BV(PC3); // S[1..4] are input<br />
PORTC |= _BV(PC0) | _BV(PC1) | _BV(PC2) | _BV(PC3); // use pullup for S[1..4]<br />
<br />
// wait for pullops to "settle down"<br />
wait(1000);<br />
<br />
while (1) { <br />
record();<br />
play();<br />
}<br />
}</source><br />
<br />
== 2. Abend ==<br />
<br />
Änderungen des IR-Signals werden aufgezeichnet, und auch zeitlich ausgewertet. Messung ist jedoch relativ ungenau. Implementation von Timer / Counter fehlt.<br />
<br />
<source lang ="c"><br />
/* ################################### */<br />
/* # IR-Empfang # */<br />
/* # Von Gruppe 1 # */<br />
/* ################################### */<br />
/* # Done: IR-Signale chronologisch # */<br />
/* # aufzeichnen # */<br />
/* ################################### */<br />
/* # Todo: Counter / Timer einbauen # */<br />
/* ################################### */<br />
<br />
<br />
#include <avr/io.h><br />
#include <string.h><br />
#include <stdio.h><br />
#include <avr/pgmspace.h><br />
#include <util/delay.h><br />
#include "uart.h"<br />
<br />
int main(void)<br />
{<br />
int status = 0;<br />
int counter = 0;<br />
/* initialize serial uart */<br />
uart_init();<br />
<br />
/* configure irrx as input */<br />
DDRC &= ~_BV(PC3);<br />
<br />
/* init led pin as output */<br />
DDRD |= _BV(PD3);<br />
<br />
while(1) {<br />
counter++;<br />
for (int i = 0; i<10; i++)<br />
{<br />
_delay_us(10);<br />
}<br />
/* if ir rx is high, turn off led */<br />
if (PINC & _BV(PC3)) {<br />
// Kein IR<br />
PORTD &= ~_BV(PD3);<br />
if (status == 1)<br />
{<br />
uart_printf("Ir jetzt aus %u\n",counter);<br />
counter = 0;<br />
}<br />
status = 0;<br />
<br />
} else {<br />
PORTD |= _BV(PD3);<br />
if (status == 0)<br />
{<br />
uart_printf("Ir jetzt an %u\n",counter);<br />
counter = 0;<br />
}<br />
status = 1;<br />
}<br />
}<br />
}<br />
</source><br />
<br />
== 3. Abend ==<br />
=== IR-Jammer ===<br />
Sendet, sobald er IR empfängt, für 1000ms und wartet dann 5ms, damit er das ausgesandte Signal nicht wieder empfängt.<br />
<br />
<source lang="c"><br />
#include <avr/io.h><br />
#include <avr/interrupt.h><br />
#include <util/delay.h><br />
#include "uart.h"<br />
<br />
/* constants */<br />
#define MAX 160<br />
/* 38khz: freq = F_CPU/(2*prescaler*frequency)<br />
* 20mhz/(2*8*38khz) = ~33<br />
* real frequency: 20mhz/(2*8*33) = ~37878Hz */<br />
#define PWM_FREQ 33<br />
<br />
/* global variables */<br />
<br />
/* allocate 160*2 = 320 byte memory for storing a code,<br />
* this means we can store 80 on/off sequence timings */<br />
volatile uint16_t code[MAX];<br />
/* current index in code[] (default: 0) */<br />
volatile uint8_t pos = 0;<br />
/* current pin state (default: high == idle) */<br />
volatile uint8_t state = 1;<br />
/* signal for the main application that a code has been received<br />
* (default: 0) */<br />
volatile uint8_t done = 0;<br />
/* signal button presses from interrupt to main */<br />
volatile uint8_t button_press;<br />
/* current system mode */<br />
enum {<br />
MODE_OFF = 0,<br />
MODE_DISPLAY = 1,<br />
MODE_JAM = 2,<br />
MODE_RECORD = 3,<br />
} mode = MODE_DISPLAY;<br />
/* current viewmode */<br />
enum {<br />
VIEW_VALUE_AND_TIME = 0,<br />
VIEW_VALUE = 1,<br />
VIEW_TIME = 2,<br />
} view = VIEW_VALUE_AND_TIME;<br />
<br />
/* call every 10 ms, for buttons at pins PC0-PC3 */<br />
static uint8_t button_sample(void)<br />
{<br />
/* initialize state, buttons are active low! */<br />
static uint8_t btn_state = 15; //0b1111;<br />
/* initialize old sample */<br />
static uint8_t last_sample = 15; //0b1111;<br />
/* read inputs */<br />
uint8_t new_sample = PINC & 15; //0b1111;<br />
<br />
/* mark bits which are sampled with the same value */<br />
uint8_t same_sample = (last_sample ^ ~new_sample);<br />
/* all bits set in same_sample now have been sampled with the same value<br />
* at least two times, which means the button has settled */<br />
<br />
/* compare the current button state with the most recent sampled value,<br />
* but only for those bits which have stayed the same */<br />
uint8_t state_different = btn_state ^ (new_sample & same_sample);<br />
/* all bits set in state_different have been sampled at least two times<br />
* with the same value, and this value is different from the current<br />
* button state */<br />
<br />
/* if a bit is set in state (means: button is not pressed) AND bit is set<br />
* in state_different (means: input has settled and value is different<br />
* from state) together means: button has been pressed recently */<br />
uint8_t btn_press = btn_state & state_different;<br />
<br />
/* toggle all bits for inputs which switched state */<br />
btn_state ^= state_different;<br />
<br />
/* store current sample for next time */<br />
last_sample = new_sample;<br />
<br />
/* if bit is set in btn_press, a button has been pressed<br />
* (not released yet) */<br />
return btn_press;<br />
}<br />
<br />
void wait(uint32_t s) {<br />
uint32_t i;<br />
for (i = 0; i < s; i++) {<br />
_delay_ms(1);<br />
}<br />
}<br />
<br />
/* set up timer 0 to generate a carrier using pwm at freq on pin OC0B (PD5) */<br />
static void ir_enable(uint8_t freq) {<br />
/* timer 0: fast pwm mode, clear OC0B on match, prescaler 8 */<br />
TCCR0A = _BV(WGM00) | _BV(COM0B1);<br />
TCCR0B = _BV(CS01) | _BV(WGM02);<br />
<br />
/* set frequency */<br />
OCR0A = freq;<br />
<br />
/* set duty-cycle to 50% */<br />
OCR0B = freq/2;<br />
}<br />
<br />
/* disable timer 0 and pwm generation */<br />
static void ir_disable(void) {<br />
TCCR0A = 0;<br />
TCCR0B = 0;<br />
}<br />
<br />
<br />
/* pin change interrupt 1 service function */<br />
ISR(PCINT1_vect)<br />
{<br />
/* do nothing if we are just processing a code in the main loop,<br />
* or no more space is available for a timer value */<br />
if (done || pos == MAX)<br />
return;<br />
<br />
/* if this would be the first timing value ever recorded, and the<br />
* state before was high (=idle), do not record the timing value<br />
* and just reset the timer */<br />
if (state && pos == 0) {<br />
TCNT1 = 0;<br />
/* else record the timing value */<br />
} else {<br />
/* store current timer value in code[]<br />
* and reset the timer */<br />
code[pos++] = TCNT1;<br />
TCNT1 = 0;<br />
}<br />
<br />
/* toggle second led */<br />
PORTD ^= _BV(PD3);<br />
<br />
/* toggle state */<br />
state = !state;<br />
}<br />
<br />
/* timer 1 compare A interrupt service function */<br />
ISR(TIMER1_COMPA_vect)<br />
{<br />
/* do nothing if we are just processing a code in the main loop */<br />
if (done)<br />
return;<br />
<br />
/* if some code has been received */<br />
if (pos > 0) {<br />
/* if pos is odd, one last 'off'-timing is missing, fill with zero */<br />
if (pos % 2 == 1)<br />
code[pos++] = 0;<br />
<br />
/* signal main */<br />
done = 1;<br />
<br />
/* turn on third led */<br />
PORTD |= _BV(PD6);<br />
}<br />
}<br />
<br />
/* timer 2 compare A interrupt service function */<br />
ISR(TIMER2_COMPA_vect)<br />
{<br />
/* sample buttons every 10ms */<br />
button_press |= button_sample();<br />
}<br />
<br />
int main(void)<br />
{<br />
/* initialize uart */<br />
uart_init();<br />
uart_printf("rumpus ir analyzer\n");<br />
<br />
/* configure led pins as outputs and turn leds off */<br />
DDRC |= _BV(PC4);<br />
DDRD |= _BV(PD3) | _BV(PD6) | _BV(PD7);<br />
PORTC &= ~_BV(PC4);<br />
PORTD &= ~(_BV(PD3) | _BV(PD6) | _BV(PD7));<br />
<br />
/* configure ir input pin, with pullup */<br />
DDRC &= ~_BV(PC3);<br />
PORTC |= _BV(PC3);<br />
<br />
/* configure button input pins, with pullup */<br />
DDRC &= ~(_BV(PC0) | _BV(PC1) | _BV(PC2) | _BV(PC3));<br />
PORTC |= _BV(PC0) | _BV(PC1) | _BV(PC2) | _BV(PC3);<br />
<br />
/* configure ir send pin as output, set low */<br />
DDRD |= _BV(PD5);<br />
PORTD &= ~_BV(PD5);<br />
<br />
/* wait until pin is high (no ir carrier is detected) */<br />
while(!(PINC & _BV(PC3)));<br />
<br />
/* enable pin change interrupt 1 for ir input pin (PC3/PCINT11) */<br />
PCMSK1 |= _BV(PCINT11);<br />
PCICR |= _BV(PCIE1);<br />
<br />
/* configure timer1 with prescaler 64 and CTC for measuring ir timings */<br />
TCCR1B = _BV(CS11) | _BV(CS10) | _BV(WGM12);<br />
/* configure timer action after 200ms: 20mhz/64/5 */<br />
OCR1A = F_CPU/5/64;<br />
/* enable OCR1A interrupt */<br />
TIMSK1 = _BV(OCIE1A);<br />
<br />
/* configure timer 2 with prescaler 1024 and CTC<br />
* for button sampling */<br />
TCCR2A = _BV(WGM21);<br />
TCCR2B = _BV(CS22) | _BV(CS21) | _BV(CS20);<br />
/* configure compare event a to occur after 10ms and enable interrupt */<br />
OCR2A = F_CPU/1024/100;<br />
TIMSK2 = _BV(OCIE2A);<br />
<br />
/* signal user availability by turning on led 1 */<br />
PORTC |= _BV(PC4);<br />
<br />
/* enable interrupts */<br />
sei();<br />
<br />
/* signal the user that the analyzer part has started by turning led 1 on */<br />
PORTC |= _BV(PC3);<br />
<br />
while(1) {<br />
/* if a code has been received */<br />
if (mode == MODE_DISPLAY && done) {<br />
<br />
/* print code to serial uart */<br />
uart_printf("complete code received, %u on-off-timings:\n", pos/2);<br />
for (uint8_t i = 0; i < pos; i += 2) {<br />
<br />
if (view == VIEW_VALUE_AND_TIME) {<br />
uint32_t on, off;<br />
<br />
/* compute timing in microseconds */<br />
on = ((uint32_t)code[i]) * 64 / 20;<br />
off = ((uint32_t)code[i+1]) * 64 / 20;<br />
<br />
uart_printf(" %5lu us (%5u) on, %5lu us (%5u) off\n",<br />
on, code[i],<br />
off, code[i+1]);<br />
} else if (view == VIEW_VALUE) {<br />
uart_printf(" %5u on, %5u off\n",<br />
code[i], code[i+1]);<br />
} else if (view == VIEW_TIME) {<br />
uint32_t on, off;<br />
<br />
/* compute timing in microseconds */<br />
on = ((uint32_t)code[i]) * 64 / 20;<br />
off = ((uint32_t)code[i+1]) * 64 / 20;<br />
<br />
uart_printf(" %5lu us on, %5lu us off\n",<br />
on, off);<br />
}<br />
}<br />
<br />
<br />
/* turn off second and third led */<br />
PORTD &= ~(_BV(PD3) | _BV(PD6));<br />
<br />
/* wait until pin is high (no ir carrier is detected) */<br />
while(!(PINC & _BV(PC3)));<br />
<br />
/* reset all global variables */<br />
pos = 0;<br />
state = 1;<br />
done = 0;<br />
}<br />
<br />
if (mode == MODE_JAM) {<br />
// hier wird gejammt!<br />
<br />
if (!state) {<br />
DDRC |= _BV(PC3); // ir empfang aus<br />
<br />
ir_enable(PWM_FREQ);<br />
wait(1000);<br />
ir_disable();<br />
<br />
wait(5); // damit wir unser eben gesendetes signal nicht empfangen<br />
DDRC &= ~_BV(PC3); // ir empfang an<br />
<br />
done = 0;<br />
pos = 0;<br />
}<br />
}<br />
<br />
if (button_press) {<br />
/* first button toggles system mode */<br />
if (button_press & 1) {<br />
mode++;<br />
if (mode > MODE_RECORD)<br />
mode = MODE_OFF;<br />
<br />
if (mode == MODE_OFF) {<br />
uart_printf("ir analyzer switched off\n");<br />
<br />
/* disable timer1 and pin change interrupts */<br />
TIMSK1 &= ~_BV(OCIE1A);<br />
PCMSK1 &= ~_BV(PCINT11);<br />
<br />
/* turn off led1 */<br />
PORTC &= ~_BV(PC4);<br />
<br />
} else if (mode == MODE_DISPLAY) {<br />
uart_printf("scan and display codes\n");<br />
<br />
/* clear interrupt flags, enable timer1 and pin change interrupts */<br />
TIFR1 = _BV(OCIE1A);<br />
TIMSK1 |= _BV(OCIE1A);<br />
PCMSK1 |= _BV(PCINT11);<br />
<br />
/* turn on led1 */<br />
PORTC |= _BV(PC4);<br />
} else if (mode == MODE_JAM) {<br />
/* clear interrupt flags, enable timer1 and pin change interrupts */<br />
TIFR1 = _BV(OCIE1A);<br />
TIMSK1 |= _BV(OCIE1A);<br />
PCMSK1 |= _BV(PCINT11);<br />
<br />
uart_printf("jamming mode active\n");<br />
} else if (mode == MODE_RECORD) {<br />
uart_printf("record and replay a code\n");<br />
}<br />
}<br />
<br />
<br />
/* second button toggles view mode */<br />
if (button_press & 2) {<br />
view++;<br />
if (view > VIEW_TIME)<br />
view = VIEW_VALUE_AND_TIME;<br />
<br />
if (view == VIEW_VALUE_AND_TIME)<br />
uart_printf("display timer value and time (in us)\n");<br />
else if (view == VIEW_VALUE)<br />
uart_printf("display timer value\n");<br />
else if (view == VIEW_TIME)<br />
uart_printf("display time (in us)\n");<br />
}<br />
<br />
if (button_press & 4) {<br />
static uint8_t pwm = 0;<br />
<br />
if (!pwm) {<br />
ir_enable(PWM_FREQ);<br />
uart_printf("pwm on\n");<br />
} else {<br />
ir_disable();<br />
uart_printf("pwm off\n");<br />
}<br />
pwm = !pwm;<br />
}<br />
<br />
button_press = 0;<br />
}<br />
}<br />
}</source><br />
<br />
== 4. Abend ==<br />
=== IR-Jammer in schlau ===<br />
Misst die kürzeste Impulsdauer und sendet mit dieser (plus einer kleinen, sich ändernden Verzögerung) in die Pausen.<br />
<br />
<source lang="c">#include <avr/io.h><br />
#include <avr/interrupt.h><br />
#include <util/delay.h><br />
#include "uart.h"<br />
<br />
/* constants */<br />
#define MAX 160<br />
/* 38khz: freq = F_CPU/(2*prescaler*frequency)<br />
* 20mhz/(2*8*38khz) = ~33<br />
* real frequency: 20mhz/(2*8*33) = ~37878Hz */<br />
#define PWM_FREQ 33<br />
<br />
/* global variables */<br />
<br />
/* allocate 160*2 = 320 byte memory for storing a code,<br />
* this means we can store 80 on/off sequence timings */<br />
volatile uint16_t code[MAX];<br />
/* current index in code[] (default: 0) */<br />
volatile uint8_t pos = 0;<br />
/* current pin state (default: high == idle) */<br />
volatile uint8_t state = 1;<br />
/* signal for the main application that a code has been received<br />
* (default: 0) */<br />
volatile uint8_t done = 0;<br />
/* signal button presses from interrupt to main */<br />
volatile uint8_t button_press;<br />
/* current system mode */<br />
enum {<br />
MODE_OFF = 0,<br />
MODE_DISPLAY = 1,<br />
MODE_JAM = 2,<br />
MODE_RECORD = 3,<br />
} mode = MODE_DISPLAY;<br />
/* current viewmode */<br />
enum {<br />
VIEW_VALUE_AND_TIME = 0,<br />
VIEW_VALUE = 1,<br />
VIEW_TIME = 2,<br />
} view = VIEW_VALUE_AND_TIME;<br />
<br />
/* call every 10 ms, for buttons at pins PC0-PC3 */<br />
static uint8_t button_sample(void)<br />
{<br />
/* initialize state, buttons are active low! */<br />
static uint8_t btn_state = 15; //0b1111;<br />
/* initialize old sample */<br />
static uint8_t last_sample = 15; //0b1111;<br />
/* read inputs */<br />
uint8_t new_sample = PINC & 15; //0b1111;<br />
<br />
/* mark bits which are sampled with the same value */<br />
uint8_t same_sample = (last_sample ^ ~new_sample);<br />
/* all bits set in same_sample now have been sampled with the same value<br />
* at least two times, which means the button has settled */<br />
<br />
/* compare the current button state with the most recent sampled value,<br />
* but only for those bits which have stayed the same */<br />
uint8_t state_different = btn_state ^ (new_sample & same_sample);<br />
/* all bits set in state_different have been sampled at least two times<br />
* with the same value, and this value is different from the current<br />
* button state */<br />
<br />
/* if a bit is set in state (means: button is not pressed) AND bit is set<br />
* in state_different (means: input has settled and value is different<br />
* from state) together means: button has been pressed recently */<br />
uint8_t btn_press = btn_state & state_different;<br />
<br />
/* toggle all bits for inputs which switched state */<br />
btn_state ^= state_different;<br />
<br />
/* store current sample for next time */<br />
last_sample = new_sample;<br />
<br />
/* if bit is set in btn_press, a button has been pressed<br />
* (not released yet) */<br />
return btn_press;<br />
}<br />
<br />
static void wait(uint32_t s) {<br />
uint32_t i;<br />
for (i = 0; i < s; i++) {<br />
_delay_us(1);<br />
}<br />
}<br />
<br />
/* set up timer 0 to generate a carrier using pwm at freq on pin OC0B (PD5) */<br />
static void ir_enable(uint8_t freq) {<br />
/* timer 0: fast pwm mode, clear OC0B on match, prescaler 8 */<br />
TCCR0A = _BV(WGM00) | _BV(COM0B1);<br />
TCCR0B = _BV(CS01) | _BV(WGM02);<br />
<br />
/* set frequency */<br />
OCR0A = freq;<br />
<br />
/* set duty-cycle to 50% */<br />
OCR0B = freq/2;<br />
}<br />
<br />
/* disable timer 0 and pwm generation */<br />
static void ir_disable(void) {<br />
TCCR0A = 0;<br />
TCCR0B = 0;<br />
}<br />
<br />
static void jam(void) {<br />
static uint32_t dur;<br />
static uint16_t i;<br />
uint8_t j = 0;<br />
uint32_t dur_tmp;<br />
<br />
if (pos == 0 || done) {<br />
dur = 0xFFFFFFFF;<br />
}<br />
<br />
if (i % 500 == 0) {<br />
i=0;<br />
if (!state) {<br />
uart_printf("-");<br />
} else {<br />
uart_printf(".");<br />
}<br />
}<br />
i++;<br />
<br />
<br />
if (pos < 1) {<br />
return;<br />
}<br />
<br />
// shortest measured duration<br />
dur_tmp = ((uint32_t)code[pos-1]) * 64 / 20;<br />
dur = dur_tmp < dur ? dur_tmp : dur;<br />
<br />
while (!state && j < 10) {<br />
j++;<br />
DDRC |= _BV(PC3); // ir reciever off<br />
<br />
ir_enable(PWM_FREQ);<br />
uart_printf("*");<br />
wait(dur+i);<br />
ir_disable();<br />
<br />
wait(250); // we don't want to recieve our own signal (due to lags in the ir receiver)<br />
DDRC &= ~_BV(PC3); // ir reciever on<br />
}<br />
}<br />
<br />
/* pin change interrupt 1 service function */<br />
ISR(PCINT1_vect)<br />
{<br />
/* do nothing if we are just processing a code in the main loop,<br />
* or no more space is available for a timer value */<br />
if (done || pos == MAX)<br />
return;<br />
<br />
/* if this would be the first timing value ever recorded, and the<br />
* state before was high (=idle), do not record the timing value<br />
* and just reset the timer */<br />
if (state && pos == 0) {<br />
TCNT1 = 0;<br />
/* else record the timing value */<br />
} else {<br />
/* store current timer value in code[]<br />
* and reset the timer */<br />
code[pos++] = TCNT1;<br />
TCNT1 = 0;<br />
}<br />
<br />
/* toggle second led */<br />
PORTD ^= _BV(PD3);<br />
<br />
/* toggle state */<br />
state = !state;<br />
}<br />
<br />
/* timer 1 compare A interrupt service function */<br />
ISR(TIMER1_COMPA_vect)<br />
{<br />
/* do nothing if we are just processing a code in the main loop */<br />
if (done)<br />
return;<br />
<br />
/* if some code has been received */<br />
if (pos > 0) {<br />
/* if pos is odd, one last 'off'-timing is missing, fill with zero */<br />
if (pos % 2 == 1)<br />
code[pos++] = 0;<br />
<br />
/* signal main */<br />
done = 1;<br />
<br />
/* turn on third led */<br />
PORTD |= _BV(PD6);<br />
}<br />
}<br />
<br />
/* timer 2 compare A interrupt service function */<br />
ISR(TIMER2_COMPA_vect)<br />
{<br />
/* sample buttons every 10ms */<br />
button_press |= button_sample();<br />
}<br />
<br />
int main(void)<br />
{<br />
/* initialize uart */<br />
uart_init();<br />
uart_printf("rumpus ir analyzer\n");<br />
<br />
/* configure led pins as outputs and turn leds off */<br />
DDRC |= _BV(PC4);<br />
DDRD |= _BV(PD3) | _BV(PD6) | _BV(PD7);<br />
PORTC &= ~_BV(PC4);<br />
PORTD &= ~(_BV(PD3) | _BV(PD6) | _BV(PD7));<br />
<br />
/* configure ir input pin, with pullup */<br />
DDRC &= ~_BV(PC3);<br />
PORTC |= _BV(PC3);<br />
<br />
/* configure button input pins, with pullup */<br />
DDRC &= ~(_BV(PC0) | _BV(PC1) | _BV(PC2) | _BV(PC3));<br />
PORTC |= _BV(PC0) | _BV(PC1) | _BV(PC2) | _BV(PC3);<br />
<br />
/* configure ir send pin as output, set low */<br />
DDRD |= _BV(PD5);<br />
PORTD &= ~_BV(PD5);<br />
<br />
/* wait until pin is high (no ir carrier is detected) */<br />
while(!(PINC & _BV(PC3)));<br />
<br />
/* enable pin change interrupt 1 for ir input pin (PC3/PCINT11) */<br />
PCMSK1 |= _BV(PCINT11);<br />
PCICR |= _BV(PCIE1);<br />
<br />
/* configure timer1 with prescaler 64 and CTC for measuring ir timings */<br />
TCCR1B = _BV(CS11) | _BV(CS10) | _BV(WGM12);<br />
/* configure timer action after 200ms: 20mhz/64/5 */<br />
OCR1A = F_CPU/5/64;<br />
/* enable OCR1A interrupt */<br />
TIMSK1 = _BV(OCIE1A);<br />
<br />
/* configure timer 2 with prescaler 1024 and CTC<br />
* for button sampling */<br />
TCCR2A = _BV(WGM21);<br />
TCCR2B = _BV(CS22) | _BV(CS21) | _BV(CS20);<br />
/* configure compare event a to occur after 10ms and enable interrupt */<br />
OCR2A = F_CPU/1024/100;<br />
TIMSK2 = _BV(OCIE2A);<br />
<br />
/* signal user availability by turning on led 1 */<br />
PORTC |= _BV(PC4);<br />
<br />
/* enable interrupts */<br />
sei();<br />
<br />
/* signal the user that the analyzer part has started by turning led 1 on */<br />
PORTC |= _BV(PC3);<br />
<br />
while(1) {<br />
/* if a code has been received */<br />
if (mode == MODE_DISPLAY && done) {<br />
<br />
/* print code to serial uart */<br />
uart_printf("complete code received, %u on-off-timings:\n", pos/2);<br />
for (uint8_t i = 0; i < pos; i += 2) {<br />
<br />
if (view == VIEW_VALUE_AND_TIME) {<br />
uint32_t on, off;<br />
<br />
/* compute timing in microseconds */<br />
on = ((uint32_t)code[i]) * 64 / 20;<br />
off = ((uint32_t)code[i+1]) * 64 / 20;<br />
<br />
uart_printf(" %5lu us (%5u) on, %5lu us (%5u) off\n",<br />
on, code[i],<br />
off, code[i+1]);<br />
} else if (view == VIEW_VALUE) {<br />
uart_printf(" %5u on, %5u off\n",<br />
code[i], code[i+1]);<br />
} else if (view == VIEW_TIME) {<br />
uint32_t on, off;<br />
<br />
/* compute timing in microseconds */<br />
on = ((uint32_t)code[i]) * 64 / 20;<br />
off = ((uint32_t)code[i+1]) * 64 / 20;<br />
<br />
uart_printf(" %5lu us on, %5lu us off\n",<br />
on, off);<br />
}<br />
}<br />
<br />
<br />
/* turn off second and third led */<br />
PORTD &= ~(_BV(PD3) | _BV(PD6));<br />
<br />
/* wait until pin is high (no ir carrier is detected) */<br />
while(!(PINC & _BV(PC3)));<br />
<br />
/* reset all global variables */<br />
pos = 0;<br />
state = 1;<br />
done = 0;<br />
}<br />
<br />
if (mode == MODE_JAM) {<br />
jam();<br />
}<br />
<br />
if (done) {<br />
// code completely detected<br />
<br />
/* reset all global variables */<br />
pos = 0;<br />
state = 1;<br />
done = 0;<br />
} <br />
<br />
if (button_press) {<br />
/* first button toggles system mode */<br />
if (button_press & 1) {<br />
mode++;<br />
if (mode > MODE_RECORD)<br />
mode = MODE_OFF;<br />
<br />
if (mode == MODE_OFF) {<br />
uart_printf("ir analyzer switched off\n");<br />
<br />
/* disable timer1 and pin change interrupts */<br />
TIMSK1 &= ~_BV(OCIE1A);<br />
PCMSK1 &= ~_BV(PCINT11);<br />
<br />
/* turn off led1 */<br />
PORTC &= ~_BV(PC4);<br />
<br />
} else if (mode == MODE_DISPLAY) {<br />
uart_printf("scan and display codes\n");<br />
<br />
/* clear interrupt flags, enable timer1 and pin change interrupts */<br />
TIFR1 = _BV(OCIE1A);<br />
TIMSK1 |= _BV(OCIE1A);<br />
PCMSK1 |= _BV(PCINT11);<br />
<br />
/* turn on led1 */<br />
PORTC |= _BV(PC4);<br />
} else if (mode == MODE_JAM) {<br />
/* clear interrupt flags, enable timer1 and pin change interrupts */<br />
TIFR1 = _BV(OCIE1A);<br />
TIMSK1 |= _BV(OCIE1A);<br />
PCMSK1 |= _BV(PCINT11);<br />
<br />
uart_printf("jamming mode active\n");<br />
} else if (mode == MODE_RECORD) {<br />
uart_printf("record and replay a code\n");<br />
}<br />
}<br />
<br />
<br />
/* second button toggles view mode */<br />
if (button_press & 2) {<br />
view++;<br />
if (view > VIEW_TIME)<br />
view = VIEW_VALUE_AND_TIME;<br />
<br />
if (view == VIEW_VALUE_AND_TIME)<br />
uart_printf("display timer value and time (in us)\n");<br />
else if (view == VIEW_VALUE)<br />
uart_printf("display timer value\n");<br />
else if (view == VIEW_TIME)<br />
uart_printf("display time (in us)\n");<br />
}<br />
<br />
if (button_press & 4) {<br />
static uint8_t pwm = 0;<br />
<br />
if (!pwm) {<br />
ir_enable(PWM_FREQ);<br />
uart_printf("pwm on\n");<br />
} else {<br />
ir_disable();<br />
uart_printf("pwm off\n");<br />
}<br />
pwm = !pwm;<br />
}<br />
<br />
button_press = 0;<br />
}<br />
}<br />
}</source><br />
<br />
=== Eigener Chat (Test) ===<br />
<source lang="c">#include <avr/io.h><br />
#include <avr/interrupt.h><br />
#include <util/delay.h><br />
#include "uart.h"<br />
<br />
/* constants */<br />
#define MAX 160<br />
/* 38khz: freq = F_CPU/(2*prescaler*frequency)<br />
* 20mhz/(2*8*38khz) = ~33<br />
* real frequency: 20mhz/(2*8*33) = ~37878Hz */<br />
#define PWM_FREQ 33<br />
<br />
/* global variables */<br />
<br />
/* allocate 160*2 = 320 byte memory for storing a code,<br />
* this means we can store 80 on/off sequence timings */<br />
volatile uint16_t code[MAX];<br />
/* current index in code[] (default: 0) */<br />
volatile uint8_t pos = 0;<br />
/* current pin state (default: high == idle) */<br />
volatile uint8_t state = 1;<br />
/* signal for the main application that a code has been received<br />
* (default: 0) */<br />
volatile uint8_t done = 0;<br />
/* signal button presses from interrupt to main */<br />
volatile uint8_t button_press;<br />
/* current system mode */<br />
enum {<br />
MODE_OFF = 0,<br />
MODE_DISPLAY = 1,<br />
MODE_JAM = 2,<br />
MODE_RECORD = 3,<br />
} mode = MODE_DISPLAY;<br />
/* current viewmode */<br />
enum {<br />
VIEW_VALUE_AND_TIME = 0,<br />
VIEW_VALUE = 1,<br />
VIEW_TIME = 2,<br />
} view = VIEW_VALUE_AND_TIME;<br />
<br />
/* call every 10 ms, for buttons at pins PC0-PC3 */<br />
static uint8_t button_sample(void)<br />
{<br />
/* initialize state, buttons are active low! */<br />
static uint8_t btn_state = 15; //0b1111;<br />
/* initialize old sample */<br />
static uint8_t last_sample = 15; //0b1111;<br />
/* read inputs */<br />
uint8_t new_sample = PINC & 15; //0b1111;<br />
<br />
/* mark bits which are sampled with the same value */<br />
uint8_t same_sample = (last_sample ^ ~new_sample);<br />
/* all bits set in same_sample now have been sampled with the same value<br />
* at least two times, which means the button has settled */<br />
<br />
/* compare the current button state with the most recent sampled value,<br />
* but only for those bits which have stayed the same */<br />
uint8_t state_different = btn_state ^ (new_sample & same_sample);<br />
/* all bits set in state_different have been sampled at least two times<br />
* with the same value, and this value is different from the current<br />
* button state */<br />
<br />
/* if a bit is set in state (means: button is not pressed) AND bit is set<br />
* in state_different (means: input has settled and value is different<br />
* from state) together means: button has been pressed recently */<br />
uint8_t btn_press = btn_state & state_different;<br />
<br />
/* toggle all bits for inputs which switched state */<br />
btn_state ^= state_different;<br />
<br />
/* store current sample for next time */<br />
last_sample = new_sample;<br />
<br />
/* if bit is set in btn_press, a button has been pressed<br />
* (not released yet) */<br />
return btn_press;<br />
}<br />
<br />
static void wait(uint32_t s) {<br />
uint32_t i;<br />
for (i = 0; i < s; i++) {<br />
_delay_ms(1);<br />
}<br />
}<br />
<br />
/* set up timer 0 to generate a carrier using pwm at freq on pin OC0B (PD5) */<br />
static void ir_enable(uint8_t freq) {<br />
/* timer 0: fast pwm mode, clear OC0B on match, prescaler 8 */<br />
TCCR0A = _BV(WGM00) | _BV(COM0B1);<br />
TCCR0B = _BV(CS01) | _BV(WGM02);<br />
<br />
/* set frequency */<br />
OCR0A = freq;<br />
<br />
/* set duty-cycle to 1/8 */<br />
OCR0B = freq/8;<br />
}<br />
<br />
/* disable timer 0 and pwm generation */<br />
static void ir_disable(void) {<br />
TCCR0A = 0;<br />
TCCR0B = 0;<br />
}<br />
<br />
<br />
/* pin change interrupt 1 service function */<br />
ISR(PCINT1_vect)<br />
{<br />
/* do nothing if we are just processing a code in the main loop,<br />
* or no more space is available for a timer value */<br />
if (done || pos == MAX)<br />
return;<br />
<br />
/* if this would be the first timing value ever recorded, and the<br />
* state before was high (=idle), do not record the timing value<br />
* and just reset the timer */<br />
if (state && pos == 0) {<br />
TCNT1 = 0;<br />
/* else record the timing value */<br />
} else {<br />
/* store current timer value in code[]<br />
* and reset the timer */<br />
code[pos++] = TCNT1;<br />
TCNT1 = 0;<br />
}<br />
<br />
/* toggle second led */<br />
PORTD ^= _BV(PD3);<br />
<br />
/* toggle state */<br />
state = !state;<br />
}<br />
<br />
/* timer 1 compare A interrupt service function */<br />
ISR(TIMER1_COMPA_vect)<br />
{<br />
/* do nothing if we are just processing a code in the main loop */<br />
if (done)<br />
return;<br />
<br />
/* if some code has been received */<br />
if (pos > 0) {<br />
/* if pos is odd, one last 'off'-timing is missing, fill with zero */<br />
if (pos % 2 == 1)<br />
code[pos++] = 0;<br />
<br />
/* signal main */<br />
done = 1;<br />
<br />
/* turn on third led */<br />
PORTD |= _BV(PD6);<br />
}<br />
}<br />
<br />
/* timer 2 compare A interrupt service function */<br />
ISR(TIMER2_COMPA_vect)<br />
{<br />
/* sample buttons every 10ms */<br />
button_press |= button_sample();<br />
}<br />
<br />
void send(uint8_t sendcode) {<br />
// uart_printf("%u\n", sendcode);<br />
<br />
// say hello<br />
ir_enable(PWM_FREQ);<br />
wait(1);<br />
ir_disable();<br />
wait(1);<br />
<br />
uart_printf("\nsend: ");<br />
for (uint8_t i = 0; i < 8; i++) {<br />
if (sendcode & (1 << i)) {<br />
// an<br />
ir_enable(PWM_FREQ);<br />
wait(1);<br />
ir_disable();<br />
uart_printf("-");<br />
} else {<br />
// aus<br />
wait(1);<br />
uart_printf(".");<br />
}<br />
<br />
wait(1);<br />
uart_printf(".");<br />
}<br />
} <br />
<br />
int main(void)<br />
{<br />
/* initialize uart */<br />
uart_init();<br />
uart_printf("rumpus ir chat\n");<br />
<br />
/* configure led pins as outputs and turn leds off */<br />
DDRC |= _BV(PC4);<br />
DDRD |= _BV(PD3) | _BV(PD6) | _BV(PD7);<br />
PORTC &= ~_BV(PC4);<br />
PORTD &= ~(_BV(PD3) | _BV(PD6) | _BV(PD7));<br />
<br />
/* configure ir input pin, with pullup */<br />
DDRC &= ~_BV(PC3);<br />
PORTC |= _BV(PC3);<br />
<br />
/* configure button input pins, with pullup */<br />
DDRC &= ~(_BV(PC0) | _BV(PC1) | _BV(PC2) | _BV(PC3));<br />
PORTC |= _BV(PC0) | _BV(PC1) | _BV(PC2) | _BV(PC3);<br />
<br />
/* configure ir send pin as output, set low */<br />
DDRD |= _BV(PD5);<br />
PORTD &= ~_BV(PD5);<br />
<br />
/* wait until pin is high (no ir carrier is detected) */<br />
while(!(PINC & _BV(PC3)));<br />
<br />
/* enable pin change interrupt 1 for ir input pin (PC3/PCINT11) */<br />
PCMSK1 |= _BV(PCINT11);<br />
PCICR |= _BV(PCIE1);<br />
<br />
/* configure timer1 with prescaler 64 and CTC for measuring ir timings */<br />
TCCR1B = _BV(CS11) | _BV(CS10) | _BV(WGM12);<br />
/* configure timer action after 200ms: 20mhz/64/5 */<br />
OCR1A = F_CPU/5/64;<br />
/* enable OCR1A interrupt */<br />
TIMSK1 = _BV(OCIE1A);<br />
<br />
/* configure timer 2 with prescaler 1024 and CTC<br />
* for button sampling */<br />
TCCR2A = _BV(WGM21);<br />
TCCR2B = _BV(CS22) | _BV(CS21) | _BV(CS20);<br />
/* configure compare event a to occur after 10ms and enable interrupt */<br />
OCR2A = F_CPU/1024/100;<br />
TIMSK2 = _BV(OCIE2A);<br />
<br />
/* signal user availability by turning on led 1 */<br />
PORTC |= _BV(PC4);<br />
<br />
/* enable interrupts */<br />
sei();<br />
<br />
/* signal the user that the analyzer part has started by turning led 1 on */<br />
PORTC |= _BV(PC3);<br />
<br />
while(1) {<br />
<br />
/* if a code has been received */<br />
if (done) {<br />
uint8_t anz_nullen;<br />
<br />
// EMPFANG<br />
uart_printf("\nempfang:");<br />
<br />
uint8_t empfang, j = 0;<br />
for (uint8_t i = 3; i < pos; i += 2) {<br />
// "aus"<br />
code[i] = code[i] * 64 / 20;<br />
anz_nullen = (code[i] - (code[i] % 2000)) / 2000;<br />
uart_printf("\ncode[i]=%u, anz_nullen=%u\n", code[i], anz_nullen);<br />
if (anz_nullen == 0) {<br />
empfang |= (1 << j);<br />
uart_printf("1");<br />
} else {<br />
for (uint8_t x = 0; x < anz_nullen; x++) {<br />
uart_printf("0");<br />
}<br />
}<br />
<br />
j += anz_nullen + 1;<br />
<br />
}<br />
<br />
uart_printf("\n");<br />
<br />
<br />
/* turn off second and third led */<br />
PORTD &= ~(_BV(PD3) | _BV(PD6));<br />
<br />
/* wait until pin is high (no ir carrier is detected) */<br />
while(!(PINC & _BV(PC3)));<br />
<br />
/* reset all global variables */<br />
pos = 0;<br />
state = 1;<br />
done = 0;<br />
}<br />
<br />
if (button_press) {<br />
/* first button toggles system mode */<br />
if (button_press) {<br />
// SENDEN<br />
if (button_press & (1 << 0)) {<br />
send(1); // 0b1<br />
} else if (button_press & (1 << 1)) {<br />
send(5); // 0b101<br />
} else if (button_press & (1 << 2)) {<br />
send(17); // 0b10001<br />
}<br />
}<br />
<br />
button_press = 0;<br />
}<br />
}<br />
}</source><br />
[[Category:U23 2008]]</div>
Hendi
https://wiki.koeln.ccc.de/index.php?title=U23_2008-2/Gruppe1&diff=14673
U23 2008-2/Gruppe1
2008-11-10T18:39:43Z
<p>Hendi: </p>
<hr />
<div>= Meta Data =<br />
== Mitglieder ==<br />
* Mark<br /><br />
* Christoph<br /><br />
* Hendrik<br /><br />
* Robert<br /><br />
<br />
= Code =<br />
== 1. Abend ==<br />
=== LED - Blinken ===<br />
: Aufgabe: Eine LED soll zum blinken gebracht werden.<br />
: Code:<br />
<source lang ="c"><br />
//****************************************************************************<br />
// * <br />
// * Von Gruppe 1<br />
// * Aufgabe: Alle LEDs sollen zum blinken gebracht werden.<br />
// * <br />
// * Task: All LED shall blink.<br />
// * <br />
//****************************************************************************<br />
<br />
#include <avr/io.h><br />
#include <util/delay.h><br />
<br />
int main(void)<br />
{<br />
/* LED Anschluss */<br />
/* LED output */<br />
/* LED1 PC4 */ <br />
/* LED2 PD3 */<br />
/* LED3 PD6 */<br />
/* LED4 PD7 */<br />
<br />
<br />
/* Setze Ports PC4, PD3, PD6 und PD7 als Ausgang */<br />
/* Set ports PC4, PD3, PD6 and PD7 as outputs */<br />
DDRC = _BV(4);<br />
DDRD = _BV(7)|_BV(6)|_BV(3);<br />
<br />
while(1)<br />
{<br />
/* _delay_ms() verzögert um 10 Millisekunden */<br />
/* 50 * 10ms = 500ms */<br />
/* _delay_ms() delays for 10 Milliseconds */<br />
/* 50 * 10ms = 500ms */<br />
for (uint8_t i=0;i<50;i++) _delay_ms(10);<br />
<br />
/* Schalte zwischen 5V und 0V an den Ausgängen hin und her */<br />
/* Toggle 5V and 0V at the outputs */<br />
PORTC ^= _BV(4);<br />
PORTD ^= _BV(7)|_BV(6)|_BV(3);<br />
}<br />
return 0;<br />
}<br />
<br />
<br />
</source><br />
<br /><br />
<br />
=== LED - Einschalten ===<br />
: Aufgabe: Eine LED soll zum leuchten gebracht werden.<br />
: Code:<br />
<source lang ="c"><br />
//****************************************************************************<br />
// * <br />
// * Von Gruppe 1<br />
// * Aufgabe: Eine LED soll zum leuchten gebracht werden.<br />
// * <br />
//****************************************************************************<br />
<br />
#include <avr/io.h><br />
<br />
int main(void)<br />
{<br />
/* PC4 auf Ausgang */<br />
DDRC = &b10000; /* Alternativ Hex: 0xF oder Dezimal: 16 */<br />
/* 7 6 5 4 3 2 1 0 */<br />
/* 0 0 0 1 0 0 0 0 */<br />
<br />
/* PC4 einschalten */<br />
PORTD = &b10000;<br />
<br />
/* Endlosschleife */<br />
while(1) <br />
{<br />
}<br />
}<br />
<br />
</source><br />
=== LED - Lauflicht ===<br />
: Code:<br />
<source lang ="c"><br />
//****************************************************************************<br />
// * <br />
// * Von Gruppe 1<br />
// * <br />
//****************************************************************************<br />
<br />
#include <avr/io.h><br />
#include <util/delay.h><br />
<br />
int main(void)<br />
{<br />
unsigned int i;<br />
<br />
/* Setze Ports PC4, PD3, PD6 und PD7 als Ausgang */<br />
DDRC = (1<<DDC4);<br />
DDRD = (1<<DDD7)|(1<<DDD6)|(1<<DDD3);<br />
/* Setze Ports PC4, PD3, PD6 und PD7 auf low */<br />
PORTC = (0<<PC4);<br />
PORTD = (0<<PD7)|(0<<PD6)|(0<<PD3);<br />
<br />
while(1)<br />
{<br />
PORTC ^= _BV(PC4);<br />
for (i=0;i<50;i++) _delay_loop_2(0);<br />
PORTC ^= _BV(PC4);<br />
PORTD ^= _BV(PD3);<br />
for (i=0;i<50;i++) _delay_loop_2(0);<br />
PORTD ^= _BV(PD3);<br />
PORTD ^= _BV(PD6);<br />
for (i=0;i<50;i++) _delay_loop_2(0);<br />
PORTD ^= _BV(PD6);<br />
PORTD ^= _BV(PD7);<br />
for (i=0;i<50;i++) _delay_loop_2(0);<br />
PORTD ^= _BV(PD7);<br />
<br />
}<br />
return 0;<br />
}<br />
</source><br />
<br />
=== Blinksequenz aufzeichnen und später abspielen ===<br />
<source lang="c">#include <avr/io.h><br />
#include <util/delay.h><br />
<br />
#define SEQS 100<br />
<br />
typedef struct {<br />
uint8_t bstate;<br />
uint32_t dur;<br />
} seq_t;<br />
<br />
seq_t seq[SEQS];<br />
uint8_t count = 0;<br />
<br />
void wait(uint32_t ms);<br />
void record(void);<br />
void play(void);<br />
<br />
void wait(uint32_t ms) {<br />
uint32_t i;<br />
<br />
for (i = 0; i < ms; i++) {<br />
_delay_ms(1);<br />
}<br />
} <br />
<br />
void record(void) {<br />
<br />
uint32_t dur = 0;<br />
uint8_t bstate_prev = 0x00; // prev button state<br />
uint8_t bstate = 0x00; // current button state<br />
<br />
while (1) {<br />
bstate = 0x00;<br />
<br />
// S1<br />
if (~PINC & _BV(PC0)) {<br />
bstate |= 1 << 1;<br />
} <br />
<br />
// S2<br />
if (~PINC & _BV(PC1)) {<br />
bstate |= 1 << 2;<br />
}<br />
<br />
// S3<br />
if (~PINC & _BV(PC2)) {<br />
bstate |= 1 << 3;<br />
}<br />
<br />
// S4<br />
if (~PINC & _BV(PC3)) {<br />
bstate |= 1 << 4;<br />
}<br />
<br />
// omit first state<br />
if (count == 0 && bstate == 0x0) {<br />
continue;<br />
}<br />
<br />
if (count >= SEQS) {<br />
// overflow error => all LEDs on<br />
while (1) {<br />
PORTC |= _BV(PC4);<br />
PORTD |= _BV(PD3) | _BV(PD6) | _BV(PD7);<br />
}<br />
}<br />
<br />
if (bstate_prev == bstate) {<br />
if (dur + 50 > dur) {<br />
dur += 50;<br />
}<br />
<br />
if (bstate == 0x0 && count > 0 && dur >= 2000) {<br />
// no button was pressed for 2s<br />
return;<br />
}<br />
} else {<br />
// save state<br />
seq[count].bstate = bstate_prev;<br />
seq[count].dur = dur;<br />
count++;<br />
<br />
// prepare for next state<br />
dur = 0;<br />
bstate_prev = bstate;<br />
}<br />
<br />
wait(50);<br />
}<br />
}<br />
<br />
void play(void) {<br />
uint8_t i;<br />
<br />
while (1) {<br />
// PORTD |= _BV(PD7);<br />
<br />
for (i = 0; i < count; i++) {<br />
// LED1<br />
if (seq[i].bstate & 1 << 1) {<br />
PORTC |= _BV(PC4);<br />
} else {<br />
PORTC &= ~_BV(PC4);<br />
}<br />
<br />
// LED2<br />
if (seq[i].bstate & 1 << 2) {<br />
PORTD |= _BV(PD3);<br />
} else {<br />
PORTD &= ~_BV(PD3);<br />
}<br />
<br />
// LED3<br />
if (seq[i].bstate & 1 << 3) {<br />
PORTD |= _BV(PD6);<br />
} else {<br />
PORTD &= ~_BV(PD6);<br />
}<br />
<br />
// LED4<br />
if (seq[i].bstate & 1 << 4) {<br />
PORTD |= _BV(PD7);<br />
} else {<br />
PORTD &= ~_BV(PD7);<br />
}<br />
<br />
wait(seq[i].dur);<br />
}<br />
<br />
PORTC &= ~_BV(PC4);<br />
PORTD &= ~_BV(PD3) & ~_BV(PD6) & ~_BV(PD7);<br />
wait(300);<br />
<br />
}<br />
}<br />
<br />
<br />
int main(void) {<br />
DDRC |= _BV(PC4);<br />
DDRD |= _BV(PD3) | _BV(PD6) | _BV(PD7); // all LEDs are output<br />
<br />
DDRC &= ~_BV(PC0) & ~_BV(PC1) & ~_BV(PC2) & ~_BV(PC3); // S[1..4] are input<br />
PORTC |= _BV(PC0) | _BV(PC1) | _BV(PC2) | _BV(PC3); // use pullup for S[1..4]<br />
<br />
// wait for pullops to "settle down"<br />
wait(1000);<br />
<br />
while (1) { <br />
record();<br />
play();<br />
}<br />
}</source><br />
<br />
== 2. Abend ==<br />
<br />
Änderungen des IR-Signals werden aufgezeichnet, und auch zeitlich ausgewertet. Messung ist jedoch relativ ungenau. Implementation von Timer / Counter fehlt.<br />
<br />
<source lang ="c"><br />
/* ################################### */<br />
/* # IR-Empfang # */<br />
/* # Von Gruppe 1 # */<br />
/* ################################### */<br />
/* # Done: IR-Signale chronologisch # */<br />
/* # aufzeichnen # */<br />
/* ################################### */<br />
/* # Todo: Counter / Timer einbauen # */<br />
/* ################################### */<br />
<br />
<br />
#include <avr/io.h><br />
#include <string.h><br />
#include <stdio.h><br />
#include <avr/pgmspace.h><br />
#include <util/delay.h><br />
#include "uart.h"<br />
<br />
int main(void)<br />
{<br />
int status = 0;<br />
int counter = 0;<br />
/* initialize serial uart */<br />
uart_init();<br />
<br />
/* configure irrx as input */<br />
DDRC &= ~_BV(PC3);<br />
<br />
/* init led pin as output */<br />
DDRD |= _BV(PD3);<br />
<br />
while(1) {<br />
counter++;<br />
for (int i = 0; i<10; i++)<br />
{<br />
_delay_us(10);<br />
}<br />
/* if ir rx is high, turn off led */<br />
if (PINC & _BV(PC3)) {<br />
// Kein IR<br />
PORTD &= ~_BV(PD3);<br />
if (status == 1)<br />
{<br />
uart_printf("Ir jetzt aus %u\n",counter);<br />
counter = 0;<br />
}<br />
status = 0;<br />
<br />
} else {<br />
PORTD |= _BV(PD3);<br />
if (status == 0)<br />
{<br />
uart_printf("Ir jetzt an %u\n",counter);<br />
counter = 0;<br />
}<br />
status = 1;<br />
}<br />
}<br />
}<br />
</source><br />
<br />
== 3. Abend ==<br />
=== IR-Jammer ===<br />
Sendet, sobald er IR empfängt, für 1000ms und wartet dann 5ms, damit er das ausgesandte Signal nicht wieder empfängt.<br />
<br />
<source lang="c"><br />
#include <avr/io.h><br />
#include <avr/interrupt.h><br />
#include <util/delay.h><br />
#include "uart.h"<br />
<br />
/* constants */<br />
#define MAX 160<br />
/* 38khz: freq = F_CPU/(2*prescaler*frequency)<br />
* 20mhz/(2*8*38khz) = ~33<br />
* real frequency: 20mhz/(2*8*33) = ~37878Hz */<br />
#define PWM_FREQ 33<br />
<br />
/* global variables */<br />
<br />
/* allocate 160*2 = 320 byte memory for storing a code,<br />
* this means we can store 80 on/off sequence timings */<br />
volatile uint16_t code[MAX];<br />
/* current index in code[] (default: 0) */<br />
volatile uint8_t pos = 0;<br />
/* current pin state (default: high == idle) */<br />
volatile uint8_t state = 1;<br />
/* signal for the main application that a code has been received<br />
* (default: 0) */<br />
volatile uint8_t done = 0;<br />
/* signal button presses from interrupt to main */<br />
volatile uint8_t button_press;<br />
/* current system mode */<br />
enum {<br />
MODE_OFF = 0,<br />
MODE_DISPLAY = 1,<br />
MODE_JAM = 2,<br />
MODE_RECORD = 3,<br />
} mode = MODE_DISPLAY;<br />
/* current viewmode */<br />
enum {<br />
VIEW_VALUE_AND_TIME = 0,<br />
VIEW_VALUE = 1,<br />
VIEW_TIME = 2,<br />
} view = VIEW_VALUE_AND_TIME;<br />
<br />
/* call every 10 ms, for buttons at pins PC0-PC3 */<br />
static uint8_t button_sample(void)<br />
{<br />
/* initialize state, buttons are active low! */<br />
static uint8_t btn_state = 15; //0b1111;<br />
/* initialize old sample */<br />
static uint8_t last_sample = 15; //0b1111;<br />
/* read inputs */<br />
uint8_t new_sample = PINC & 15; //0b1111;<br />
<br />
/* mark bits which are sampled with the same value */<br />
uint8_t same_sample = (last_sample ^ ~new_sample);<br />
/* all bits set in same_sample now have been sampled with the same value<br />
* at least two times, which means the button has settled */<br />
<br />
/* compare the current button state with the most recent sampled value,<br />
* but only for those bits which have stayed the same */<br />
uint8_t state_different = btn_state ^ (new_sample & same_sample);<br />
/* all bits set in state_different have been sampled at least two times<br />
* with the same value, and this value is different from the current<br />
* button state */<br />
<br />
/* if a bit is set in state (means: button is not pressed) AND bit is set<br />
* in state_different (means: input has settled and value is different<br />
* from state) together means: button has been pressed recently */<br />
uint8_t btn_press = btn_state & state_different;<br />
<br />
/* toggle all bits for inputs which switched state */<br />
btn_state ^= state_different;<br />
<br />
/* store current sample for next time */<br />
last_sample = new_sample;<br />
<br />
/* if bit is set in btn_press, a button has been pressed<br />
* (not released yet) */<br />
return btn_press;<br />
}<br />
<br />
void wait(uint32_t s) {<br />
uint32_t i;<br />
for (i = 0; i < s; i++) {<br />
_delay_ms(1);<br />
}<br />
}<br />
<br />
/* set up timer 0 to generate a carrier using pwm at freq on pin OC0B (PD5) */<br />
static void ir_enable(uint8_t freq) {<br />
/* timer 0: fast pwm mode, clear OC0B on match, prescaler 8 */<br />
TCCR0A = _BV(WGM00) | _BV(COM0B1);<br />
TCCR0B = _BV(CS01) | _BV(WGM02);<br />
<br />
/* set frequency */<br />
OCR0A = freq;<br />
<br />
/* set duty-cycle to 50% */<br />
OCR0B = freq/2;<br />
}<br />
<br />
/* disable timer 0 and pwm generation */<br />
static void ir_disable(void) {<br />
TCCR0A = 0;<br />
TCCR0B = 0;<br />
}<br />
<br />
<br />
/* pin change interrupt 1 service function */<br />
ISR(PCINT1_vect)<br />
{<br />
/* do nothing if we are just processing a code in the main loop,<br />
* or no more space is available for a timer value */<br />
if (done || pos == MAX)<br />
return;<br />
<br />
/* if this would be the first timing value ever recorded, and the<br />
* state before was high (=idle), do not record the timing value<br />
* and just reset the timer */<br />
if (state && pos == 0) {<br />
TCNT1 = 0;<br />
/* else record the timing value */<br />
} else {<br />
/* store current timer value in code[]<br />
* and reset the timer */<br />
code[pos++] = TCNT1;<br />
TCNT1 = 0;<br />
}<br />
<br />
/* toggle second led */<br />
PORTD ^= _BV(PD3);<br />
<br />
/* toggle state */<br />
state = !state;<br />
}<br />
<br />
/* timer 1 compare A interrupt service function */<br />
ISR(TIMER1_COMPA_vect)<br />
{<br />
/* do nothing if we are just processing a code in the main loop */<br />
if (done)<br />
return;<br />
<br />
/* if some code has been received */<br />
if (pos > 0) {<br />
/* if pos is odd, one last 'off'-timing is missing, fill with zero */<br />
if (pos % 2 == 1)<br />
code[pos++] = 0;<br />
<br />
/* signal main */<br />
done = 1;<br />
<br />
/* turn on third led */<br />
PORTD |= _BV(PD6);<br />
}<br />
}<br />
<br />
/* timer 2 compare A interrupt service function */<br />
ISR(TIMER2_COMPA_vect)<br />
{<br />
/* sample buttons every 10ms */<br />
button_press |= button_sample();<br />
}<br />
<br />
int main(void)<br />
{<br />
/* initialize uart */<br />
uart_init();<br />
uart_printf("rumpus ir analyzer\n");<br />
<br />
/* configure led pins as outputs and turn leds off */<br />
DDRC |= _BV(PC4);<br />
DDRD |= _BV(PD3) | _BV(PD6) | _BV(PD7);<br />
PORTC &= ~_BV(PC4);<br />
PORTD &= ~(_BV(PD3) | _BV(PD6) | _BV(PD7));<br />
<br />
/* configure ir input pin, with pullup */<br />
DDRC &= ~_BV(PC3);<br />
PORTC |= _BV(PC3);<br />
<br />
/* configure button input pins, with pullup */<br />
DDRC &= ~(_BV(PC0) | _BV(PC1) | _BV(PC2) | _BV(PC3));<br />
PORTC |= _BV(PC0) | _BV(PC1) | _BV(PC2) | _BV(PC3);<br />
<br />
/* configure ir send pin as output, set low */<br />
DDRD |= _BV(PD5);<br />
PORTD &= ~_BV(PD5);<br />
<br />
/* wait until pin is high (no ir carrier is detected) */<br />
while(!(PINC & _BV(PC3)));<br />
<br />
/* enable pin change interrupt 1 for ir input pin (PC3/PCINT11) */<br />
PCMSK1 |= _BV(PCINT11);<br />
PCICR |= _BV(PCIE1);<br />
<br />
/* configure timer1 with prescaler 64 and CTC for measuring ir timings */<br />
TCCR1B = _BV(CS11) | _BV(CS10) | _BV(WGM12);<br />
/* configure timer action after 200ms: 20mhz/64/5 */<br />
OCR1A = F_CPU/5/64;<br />
/* enable OCR1A interrupt */<br />
TIMSK1 = _BV(OCIE1A);<br />
<br />
/* configure timer 2 with prescaler 1024 and CTC<br />
* for button sampling */<br />
TCCR2A = _BV(WGM21);<br />
TCCR2B = _BV(CS22) | _BV(CS21) | _BV(CS20);<br />
/* configure compare event a to occur after 10ms and enable interrupt */<br />
OCR2A = F_CPU/1024/100;<br />
TIMSK2 = _BV(OCIE2A);<br />
<br />
/* signal user availability by turning on led 1 */<br />
PORTC |= _BV(PC4);<br />
<br />
/* enable interrupts */<br />
sei();<br />
<br />
/* signal the user that the analyzer part has started by turning led 1 on */<br />
PORTC |= _BV(PC3);<br />
<br />
while(1) {<br />
/* if a code has been received */<br />
if (mode == MODE_DISPLAY && done) {<br />
<br />
/* print code to serial uart */<br />
uart_printf("complete code received, %u on-off-timings:\n", pos/2);<br />
for (uint8_t i = 0; i < pos; i += 2) {<br />
<br />
if (view == VIEW_VALUE_AND_TIME) {<br />
uint32_t on, off;<br />
<br />
/* compute timing in microseconds */<br />
on = ((uint32_t)code[i]) * 64 / 20;<br />
off = ((uint32_t)code[i+1]) * 64 / 20;<br />
<br />
uart_printf(" %5lu us (%5u) on, %5lu us (%5u) off\n",<br />
on, code[i],<br />
off, code[i+1]);<br />
} else if (view == VIEW_VALUE) {<br />
uart_printf(" %5u on, %5u off\n",<br />
code[i], code[i+1]);<br />
} else if (view == VIEW_TIME) {<br />
uint32_t on, off;<br />
<br />
/* compute timing in microseconds */<br />
on = ((uint32_t)code[i]) * 64 / 20;<br />
off = ((uint32_t)code[i+1]) * 64 / 20;<br />
<br />
uart_printf(" %5lu us on, %5lu us off\n",<br />
on, off);<br />
}<br />
}<br />
<br />
<br />
/* turn off second and third led */<br />
PORTD &= ~(_BV(PD3) | _BV(PD6));<br />
<br />
/* wait until pin is high (no ir carrier is detected) */<br />
while(!(PINC & _BV(PC3)));<br />
<br />
/* reset all global variables */<br />
pos = 0;<br />
state = 1;<br />
done = 0;<br />
}<br />
<br />
if (mode == MODE_JAM) {<br />
// hier wird gejammt!<br />
<br />
if (!state) {<br />
DDRC |= _BV(PC3); // ir empfang aus<br />
<br />
ir_enable(PWM_FREQ);<br />
wait(1000);<br />
ir_disable();<br />
<br />
wait(5); // damit wir unser eben gesendetes signal nicht empfangen<br />
DDRC &= ~_BV(PC3); // ir empfang an<br />
<br />
done = 0;<br />
pos = 0;<br />
}<br />
}<br />
<br />
if (button_press) {<br />
/* first button toggles system mode */<br />
if (button_press & 1) {<br />
mode++;<br />
if (mode > MODE_RECORD)<br />
mode = MODE_OFF;<br />
<br />
if (mode == MODE_OFF) {<br />
uart_printf("ir analyzer switched off\n");<br />
<br />
/* disable timer1 and pin change interrupts */<br />
TIMSK1 &= ~_BV(OCIE1A);<br />
PCMSK1 &= ~_BV(PCINT11);<br />
<br />
/* turn off led1 */<br />
PORTC &= ~_BV(PC4);<br />
<br />
} else if (mode == MODE_DISPLAY) {<br />
uart_printf("scan and display codes\n");<br />
<br />
/* clear interrupt flags, enable timer1 and pin change interrupts */<br />
TIFR1 = _BV(OCIE1A);<br />
TIMSK1 |= _BV(OCIE1A);<br />
PCMSK1 |= _BV(PCINT11);<br />
<br />
/* turn on led1 */<br />
PORTC |= _BV(PC4);<br />
} else if (mode == MODE_JAM) {<br />
/* clear interrupt flags, enable timer1 and pin change interrupts */<br />
TIFR1 = _BV(OCIE1A);<br />
TIMSK1 |= _BV(OCIE1A);<br />
PCMSK1 |= _BV(PCINT11);<br />
<br />
uart_printf("jamming mode active\n");<br />
} else if (mode == MODE_RECORD) {<br />
uart_printf("record and replay a code\n");<br />
}<br />
}<br />
<br />
<br />
/* second button toggles view mode */<br />
if (button_press & 2) {<br />
view++;<br />
if (view > VIEW_TIME)<br />
view = VIEW_VALUE_AND_TIME;<br />
<br />
if (view == VIEW_VALUE_AND_TIME)<br />
uart_printf("display timer value and time (in us)\n");<br />
else if (view == VIEW_VALUE)<br />
uart_printf("display timer value\n");<br />
else if (view == VIEW_TIME)<br />
uart_printf("display time (in us)\n");<br />
}<br />
<br />
if (button_press & 4) {<br />
static uint8_t pwm = 0;<br />
<br />
if (!pwm) {<br />
ir_enable(PWM_FREQ);<br />
uart_printf("pwm on\n");<br />
} else {<br />
ir_disable();<br />
uart_printf("pwm off\n");<br />
}<br />
pwm = !pwm;<br />
}<br />
<br />
button_press = 0;<br />
}<br />
}<br />
}</source><br />
<br />
=== Test ===<br />
<source lang="c">#include <avr/io.h><br />
#include <avr/interrupt.h><br />
#include <util/delay.h><br />
#include "uart.h"<br />
<br />
/* constants */<br />
#define MAX 160<br />
/* 38khz: freq = F_CPU/(2*prescaler*frequency)<br />
* 20mhz/(2*8*38khz) = ~33<br />
* real frequency: 20mhz/(2*8*33) = ~37878Hz */<br />
#define PWM_FREQ 33<br />
<br />
/* global variables */<br />
<br />
/* allocate 160*2 = 320 byte memory for storing a code,<br />
* this means we can store 80 on/off sequence timings */<br />
volatile uint16_t code[MAX];<br />
/* current index in code[] (default: 0) */<br />
volatile uint8_t pos = 0;<br />
/* current pin state (default: high == idle) */<br />
volatile uint8_t state = 1;<br />
/* signal for the main application that a code has been received<br />
* (default: 0) */<br />
volatile uint8_t done = 0;<br />
/* signal button presses from interrupt to main */<br />
volatile uint8_t button_press;<br />
/* current system mode */<br />
enum {<br />
MODE_OFF = 0,<br />
MODE_DISPLAY = 1,<br />
MODE_JAM = 2,<br />
MODE_RECORD = 3,<br />
} mode = MODE_DISPLAY;<br />
/* current viewmode */<br />
enum {<br />
VIEW_VALUE_AND_TIME = 0,<br />
VIEW_VALUE = 1,<br />
VIEW_TIME = 2,<br />
} view = VIEW_VALUE_AND_TIME;<br />
<br />
/* call every 10 ms, for buttons at pins PC0-PC3 */<br />
static uint8_t button_sample(void)<br />
{<br />
/* initialize state, buttons are active low! */<br />
static uint8_t btn_state = 15; //0b1111;<br />
/* initialize old sample */<br />
static uint8_t last_sample = 15; //0b1111;<br />
/* read inputs */<br />
uint8_t new_sample = PINC & 15; //0b1111;<br />
<br />
/* mark bits which are sampled with the same value */<br />
uint8_t same_sample = (last_sample ^ ~new_sample);<br />
/* all bits set in same_sample now have been sampled with the same value<br />
* at least two times, which means the button has settled */<br />
<br />
/* compare the current button state with the most recent sampled value,<br />
* but only for those bits which have stayed the same */<br />
uint8_t state_different = btn_state ^ (new_sample & same_sample);<br />
/* all bits set in state_different have been sampled at least two times<br />
* with the same value, and this value is different from the current<br />
* button state */<br />
<br />
/* if a bit is set in state (means: button is not pressed) AND bit is set<br />
* in state_different (means: input has settled and value is different<br />
* from state) together means: button has been pressed recently */<br />
uint8_t btn_press = btn_state & state_different;<br />
<br />
/* toggle all bits for inputs which switched state */<br />
btn_state ^= state_different;<br />
<br />
/* store current sample for next time */<br />
last_sample = new_sample;<br />
<br />
/* if bit is set in btn_press, a button has been pressed<br />
* (not released yet) */<br />
return btn_press;<br />
}<br />
<br />
static void wait(uint32_t s) {<br />
uint32_t i;<br />
for (i = 0; i < s; i++) {<br />
_delay_ms(1);<br />
}<br />
}<br />
<br />
/* set up timer 0 to generate a carrier using pwm at freq on pin OC0B (PD5) */<br />
static void ir_enable(uint8_t freq) {<br />
/* timer 0: fast pwm mode, clear OC0B on match, prescaler 8 */<br />
TCCR0A = _BV(WGM00) | _BV(COM0B1);<br />
TCCR0B = _BV(CS01) | _BV(WGM02);<br />
<br />
/* set frequency */<br />
OCR0A = freq;<br />
<br />
/* set duty-cycle to 50% */<br />
OCR0B = freq/2;<br />
}<br />
<br />
/* disable timer 0 and pwm generation */<br />
static void ir_disable(void) {<br />
TCCR0A = 0;<br />
TCCR0B = 0;<br />
}<br />
<br />
static void jam(void) {<br />
static uint32_t dur;<br />
static uint16_t i;<br />
<br />
if (pos == 0 || done) {<br />
dur = 0xFFFFFFFF;<br />
}<br />
<br />
// shortest measured duration<br />
if (pos > 0) {<br />
dur = dur > (uint32_t)code[pos-1] ? (uint32_t)code[pos-1] : (dur > 0 ? 0 : 0xFFFFFFFF);<br />
uart_printf("dur=%5u\n", dur);<br />
}<br />
<br />
if (dur = 0) {<br />
return;<br />
}<br />
<br />
if (i % 500 == 0) {<br />
if (!state) {<br />
uart_printf("-");<br />
} else {<br />
uart_printf(".");<br />
}<br />
}<br />
i++;<br />
<br />
while (0 && !state) {<br />
DDRC |= _BV(PC3); // ir reciever off<br />
<br />
ir_enable(PWM_FREQ);<br />
uart_printf("\n*(%5u ms)*\n", ((uint32_t)dur) * 64 / 20);<br />
wait(dur);<br />
ir_disable();<br />
<br />
wait(50); // we don't want to recieve our own signal (due to lags in the ir receiver)<br />
DDRC &= ~_BV(PC3); // ir reciever on<br />
}<br />
}<br />
<br />
/* pin change interrupt 1 service function */<br />
ISR(PCINT1_vect)<br />
{<br />
/* do nothing if we are just processing a code in the main loop,<br />
* or no more space is available for a timer value */<br />
if (done || pos == MAX)<br />
return;<br />
<br />
/* if this would be the first timing value ever recorded, and the<br />
* state before was high (=idle), do not record the timing value<br />
* and just reset the timer */<br />
if (state && pos == 0) {<br />
TCNT1 = 0;<br />
/* else record the timing value */<br />
} else {<br />
/* store current timer value in code[]<br />
* and reset the timer */<br />
code[pos++] = TCNT1;<br />
TCNT1 = 0;<br />
}<br />
<br />
/* toggle second led */<br />
PORTD ^= _BV(PD3);<br />
<br />
/* toggle state */<br />
state = !state;<br />
}<br />
<br />
/* timer 1 compare A interrupt service function */<br />
ISR(TIMER1_COMPA_vect)<br />
{<br />
/* do nothing if we are just processing a code in the main loop */<br />
if (done)<br />
return;<br />
<br />
/* if some code has been received */<br />
if (pos > 0) {<br />
/* if pos is odd, one last 'off'-timing is missing, fill with zero */<br />
if (pos % 2 == 1)<br />
code[pos++] = 0;<br />
<br />
/* signal main */<br />
done = 1;<br />
<br />
/* turn on third led */<br />
PORTD |= _BV(PD6);<br />
}<br />
}<br />
<br />
/* timer 2 compare A interrupt service function */<br />
ISR(TIMER2_COMPA_vect)<br />
{<br />
/* sample buttons every 10ms */<br />
button_press |= button_sample();<br />
}<br />
<br />
int main(void)<br />
{<br />
/* initialize uart */<br />
uart_init();<br />
uart_printf("rumpus ir analyzer\n");<br />
<br />
/* configure led pins as outputs and turn leds off */<br />
DDRC |= _BV(PC4);<br />
DDRD |= _BV(PD3) | _BV(PD6) | _BV(PD7);<br />
PORTC &= ~_BV(PC4);<br />
PORTD &= ~(_BV(PD3) | _BV(PD6) | _BV(PD7));<br />
<br />
/* configure ir input pin, with pullup */<br />
DDRC &= ~_BV(PC3);<br />
PORTC |= _BV(PC3);<br />
<br />
/* configure button input pins, with pullup */<br />
DDRC &= ~(_BV(PC0) | _BV(PC1) | _BV(PC2) | _BV(PC3));<br />
PORTC |= _BV(PC0) | _BV(PC1) | _BV(PC2) | _BV(PC3);<br />
<br />
/* configure ir send pin as output, set low */<br />
DDRD |= _BV(PD5);<br />
PORTD &= ~_BV(PD5);<br />
<br />
/* wait until pin is high (no ir carrier is detected) */<br />
while(!(PINC & _BV(PC3)));<br />
<br />
/* enable pin change interrupt 1 for ir input pin (PC3/PCINT11) */<br />
PCMSK1 |= _BV(PCINT11);<br />
PCICR |= _BV(PCIE1);<br />
<br />
/* configure timer1 with prescaler 64 and CTC for measuring ir timings */<br />
TCCR1B = _BV(CS11) | _BV(CS10) | _BV(WGM12);<br />
/* configure timer action after 200ms: 20mhz/64/5 */<br />
OCR1A = F_CPU/5/64;<br />
/* enable OCR1A interrupt */<br />
TIMSK1 = _BV(OCIE1A);<br />
<br />
/* configure timer 2 with prescaler 1024 and CTC<br />
* for button sampling */<br />
TCCR2A = _BV(WGM21);<br />
TCCR2B = _BV(CS22) | _BV(CS21) | _BV(CS20);<br />
/* configure compare event a to occur after 10ms and enable interrupt */<br />
OCR2A = F_CPU/1024/100;<br />
TIMSK2 = _BV(OCIE2A);<br />
<br />
/* signal user availability by turning on led 1 */<br />
PORTC |= _BV(PC4);<br />
<br />
/* enable interrupts */<br />
sei();<br />
<br />
/* signal the user that the analyzer part has started by turning led 1 on */<br />
PORTC |= _BV(PC3);<br />
<br />
while(1) {<br />
/* if a code has been received */<br />
if (mode == MODE_DISPLAY && done) {<br />
<br />
/* print code to serial uart */<br />
uart_printf("complete code received, %u on-off-timings:\n", pos/2);<br />
for (uint8_t i = 0; i < pos; i += 2) {<br />
<br />
if (view == VIEW_VALUE_AND_TIME) {<br />
uint32_t on, off;<br />
<br />
/* compute timing in microseconds */<br />
on = ((uint32_t)code[i]) * 64 / 20;<br />
off = ((uint32_t)code[i+1]) * 64 / 20;<br />
<br />
uart_printf(" %5lu us (%5u) on, %5lu us (%5u) off\n",<br />
on, code[i],<br />
off, code[i+1]);<br />
} else if (view == VIEW_VALUE) {<br />
uart_printf(" %5u on, %5u off\n",<br />
code[i], code[i+1]);<br />
} else if (view == VIEW_TIME) {<br />
uint32_t on, off;<br />
<br />
/* compute timing in microseconds */<br />
on = ((uint32_t)code[i]) * 64 / 20;<br />
off = ((uint32_t)code[i+1]) * 64 / 20;<br />
<br />
uart_printf(" %5lu us on, %5lu us off\n",<br />
on, off);<br />
}<br />
}<br />
<br />
<br />
/* turn off second and third led */<br />
PORTD &= ~(_BV(PD3) | _BV(PD6));<br />
<br />
/* wait until pin is high (no ir carrier is detected) */<br />
while(!(PINC & _BV(PC3)));<br />
<br />
/* reset all global variables */<br />
pos = 0;<br />
state = 1;<br />
done = 0;<br />
}<br />
<br />
if (mode == MODE_JAM) {<br />
jam();<br />
}<br />
<br />
if (done) {<br />
// code completely detected<br />
<br />
/* reset all global variables */<br />
// pos = 0;<br />
// state = 1;<br />
// done = 0;<br />
} <br />
<br />
if (button_press) {<br />
/* first button toggles system mode */<br />
if (button_press & 1) {<br />
mode++;<br />
if (mode > MODE_RECORD)<br />
mode = MODE_OFF;<br />
<br />
if (mode == MODE_OFF) {<br />
uart_printf("ir analyzer switched off\n");<br />
<br />
/* disable timer1 and pin change interrupts */<br />
TIMSK1 &= ~_BV(OCIE1A);<br />
PCMSK1 &= ~_BV(PCINT11);<br />
<br />
/* turn off led1 */<br />
PORTC &= ~_BV(PC4);<br />
<br />
} else if (mode == MODE_DISPLAY) {<br />
uart_printf("scan and display codes\n");<br />
<br />
/* clear interrupt flags, enable timer1 and pin change interrupts */<br />
TIFR1 = _BV(OCIE1A);<br />
TIMSK1 |= _BV(OCIE1A);<br />
PCMSK1 |= _BV(PCINT11);<br />
<br />
/* turn on led1 */<br />
PORTC |= _BV(PC4);<br />
} else if (mode == MODE_JAM) {<br />
/* clear interrupt flags, enable timer1 and pin change interrupts */<br />
TIFR1 = _BV(OCIE1A);<br />
TIMSK1 |= _BV(OCIE1A);<br />
PCMSK1 |= _BV(PCINT11);<br />
<br />
uart_printf("jamming mode active\n");<br />
} else if (mode == MODE_RECORD) {<br />
uart_printf("record and replay a code\n");<br />
}<br />
}<br />
<br />
<br />
/* second button toggles view mode */<br />
if (button_press & 2) {<br />
view++;<br />
if (view > VIEW_TIME)<br />
view = VIEW_VALUE_AND_TIME;<br />
<br />
if (view == VIEW_VALUE_AND_TIME)<br />
uart_printf("display timer value and time (in us)\n");<br />
else if (view == VIEW_VALUE)<br />
uart_printf("display timer value\n");<br />
else if (view == VIEW_TIME)<br />
uart_printf("display time (in us)\n");<br />
}<br />
<br />
if (button_press & 4) {<br />
static uint8_t pwm = 0;<br />
<br />
if (!pwm) {<br />
ir_enable(PWM_FREQ);<br />
uart_printf("pwm on\n");<br />
} else {<br />
ir_disable();<br />
uart_printf("pwm off\n");<br />
}<br />
pwm = !pwm;<br />
}<br />
<br />
button_press = 0;<br />
}<br />
}<br />
}</source><br />
[[Category:U23 2008]]</div>
Hendi
https://wiki.koeln.ccc.de/index.php?title=U23_2008-2/Gruppe1&diff=14660
U23 2008-2/Gruppe1
2008-11-03T21:29:38Z
<p>Hendi: Record&Play -- Ir-Jammer</p>
<hr />
<div>= Meta Data =<br />
== Mitglieder ==<br />
* Mark<br /><br />
* Christoph<br /><br />
* Hendrik<br /><br />
* Robert<br /><br />
<br />
= Code =<br />
== 1. Abend ==<br />
=== LED - Blinken ===<br />
: Aufgabe: Eine LED soll zum blinken gebracht werden.<br />
: Code:<br />
<source lang ="c"><br />
//****************************************************************************<br />
// * <br />
// * Von Gruppe 1<br />
// * Aufgabe: Eine LED soll zum blinken gebracht werden.<br />
// * Lösung: Alle LEDs werden zum blinken gebracht<br />
// * <br />
//****************************************************************************<br />
<br />
#include <avr/io.h><br />
#include <util/delay.h><br />
<br />
int main(void)<br />
{<br />
unsigned int i;<br />
<br />
/* Setze Ports PC4, PD3, PD6 und PD7 als Ausgang */<br />
DDRC = (1<<DDC4);<br />
DDRD = (1<<DDD7)|(1<<DDD6)|(1<<DDD3);<br />
/* Setze Ports PC4, PD3, PD6 und PD7 auf high */<br />
PORTC = (1<<PC4);<br />
PORTD = (1<<PD7)|(1<<PD6)|(1<<PD3);<br />
<br />
while(1)<br />
{<br />
for (i=0;i<50;i++) _delay_loop_2(0);<br />
PORTC ^= _BV(PC4);<br />
PORTD ^= _BV(PD7)|_BV(PD6)|_BV(PD3);<br />
}<br />
return 0;<br />
}<br />
<br />
</source><br />
<br /><br />
<br />
=== LED - Einschalten ===<br />
: Aufgabe: Eine LED soll zum leuchten gebracht werden.<br />
: Code:<br />
<source lang ="c"><br />
//****************************************************************************<br />
// * <br />
// * Von Gruppe 1<br />
// * Aufgabe: Eine LED soll zum leuchten gebracht werden.<br />
// * <br />
//****************************************************************************<br />
<br />
#include <avr/io.h><br />
<br />
int main(void)<br />
{<br />
/* PC4 auf Ausgang */<br />
DDRC = &b10000; /* Alternativ Hex: 0xF oder Dezimal: 16 */<br />
/* 7 6 5 4 3 2 1 0 */<br />
/* 0 0 0 1 0 0 0 0 */<br />
<br />
/* PC4 einschalten */<br />
PORTD = &b10000;<br />
<br />
/* Endlosschleife */<br />
while(1) <br />
{<br />
}<br />
}<br />
<br />
</source><br />
=== LED - Lauflicht ===<br />
: Code:<br />
<source lang ="c"><br />
//****************************************************************************<br />
// * <br />
// * Von Gruppe 1<br />
// * <br />
//****************************************************************************<br />
<br />
#include <avr/io.h><br />
#include <util/delay.h><br />
<br />
int main(void)<br />
{<br />
unsigned int i;<br />
<br />
/* Setze Ports PC4, PD3, PD6 und PD7 als Ausgang */<br />
DDRC = (1<<DDC4);<br />
DDRD = (1<<DDD7)|(1<<DDD6)|(1<<DDD3);<br />
/* Setze Ports PC4, PD3, PD6 und PD7 auf low */<br />
PORTC = (0<<PC4);<br />
PORTD = (0<<PD7)|(0<<PD6)|(0<<PD3);<br />
<br />
while(1)<br />
{<br />
PORTC ^= _BV(PC4);<br />
for (i=0;i<50;i++) _delay_loop_2(0);<br />
PORTC ^= _BV(PC4);<br />
PORTD ^= _BV(PD3);<br />
for (i=0;i<50;i++) _delay_loop_2(0);<br />
PORTD ^= _BV(PD3);<br />
PORTD ^= _BV(PD6);<br />
for (i=0;i<50;i++) _delay_loop_2(0);<br />
PORTD ^= _BV(PD6);<br />
PORTD ^= _BV(PD7);<br />
for (i=0;i<50;i++) _delay_loop_2(0);<br />
PORTD ^= _BV(PD7);<br />
<br />
}<br />
return 0;<br />
}<br />
</source><br />
<br />
=== Blinksequenz aufzeichnen und später abspielen ===<br />
<source lang="c">#include <avr/io.h><br />
#include <util/delay.h><br />
<br />
#define SEQS 100<br />
<br />
typedef struct {<br />
uint8_t bstate;<br />
uint32_t dur;<br />
} seq_t;<br />
<br />
seq_t seq[SEQS];<br />
uint8_t count = 0;<br />
<br />
void wait(uint32_t ms);<br />
void record(void);<br />
void play(void);<br />
<br />
void wait(uint32_t ms) {<br />
uint32_t i;<br />
<br />
for (i = 0; i < ms; i++) {<br />
_delay_ms(1);<br />
}<br />
} <br />
<br />
void record(void) {<br />
<br />
uint32_t dur = 0;<br />
uint8_t bstate_prev = 0x00; // prev button state<br />
uint8_t bstate = 0x00; // current button state<br />
<br />
while (1) {<br />
bstate = 0x00;<br />
<br />
// S1<br />
if (~PINC & _BV(PC0)) {<br />
bstate |= 1 << 1;<br />
} <br />
<br />
// S2<br />
if (~PINC & _BV(PC1)) {<br />
bstate |= 1 << 2;<br />
}<br />
<br />
// S3<br />
if (~PINC & _BV(PC2)) {<br />
bstate |= 1 << 3;<br />
}<br />
<br />
// S4<br />
if (~PINC & _BV(PC3)) {<br />
bstate |= 1 << 4;<br />
}<br />
<br />
// omit first state<br />
if (count == 0 && bstate == 0x0) {<br />
continue;<br />
}<br />
<br />
if (count >= SEQS) {<br />
// overflow error => all LEDs on<br />
while (1) {<br />
PORTC |= _BV(PC4);<br />
PORTD |= _BV(PD3) | _BV(PD6) | _BV(PD7);<br />
}<br />
}<br />
<br />
if (bstate_prev == bstate) {<br />
if (dur + 50 > dur) {<br />
dur += 50;<br />
}<br />
<br />
if (bstate == 0x0 && count > 0 && dur >= 2000) {<br />
// no button was pressed for 2s<br />
return;<br />
}<br />
} else {<br />
// save state<br />
seq[count].bstate = bstate_prev;<br />
seq[count].dur = dur;<br />
count++;<br />
<br />
// prepare for next state<br />
dur = 0;<br />
bstate_prev = bstate;<br />
}<br />
<br />
wait(50);<br />
}<br />
}<br />
<br />
void play(void) {<br />
uint8_t i;<br />
<br />
while (1) {<br />
// PORTD |= _BV(PD7);<br />
<br />
for (i = 0; i < count; i++) {<br />
// LED1<br />
if (seq[i].bstate & 1 << 1) {<br />
PORTC |= _BV(PC4);<br />
} else {<br />
PORTC &= ~_BV(PC4);<br />
}<br />
<br />
// LED2<br />
if (seq[i].bstate & 1 << 2) {<br />
PORTD |= _BV(PD3);<br />
} else {<br />
PORTD &= ~_BV(PD3);<br />
}<br />
<br />
// LED3<br />
if (seq[i].bstate & 1 << 3) {<br />
PORTD |= _BV(PD6);<br />
} else {<br />
PORTD &= ~_BV(PD6);<br />
}<br />
<br />
// LED4<br />
if (seq[i].bstate & 1 << 4) {<br />
PORTD |= _BV(PD7);<br />
} else {<br />
PORTD &= ~_BV(PD7);<br />
}<br />
<br />
wait(seq[i].dur);<br />
}<br />
<br />
PORTC &= ~_BV(PC4);<br />
PORTD &= ~_BV(PD3) & ~_BV(PD6) & ~_BV(PD7);<br />
wait(300);<br />
<br />
}<br />
}<br />
<br />
<br />
int main(void) {<br />
DDRC |= _BV(PC4);<br />
DDRD |= _BV(PD3) | _BV(PD6) | _BV(PD7); // all LEDs are output<br />
<br />
DDRC &= ~_BV(PC0) & ~_BV(PC1) & ~_BV(PC2) & ~_BV(PC3); // S[1..4] are input<br />
PORTC |= _BV(PC0) | _BV(PC1) | _BV(PC2) | _BV(PC3); // use pullup for S[1..4]<br />
<br />
// wait for pullops to "settle down"<br />
wait(1000);<br />
<br />
while (1) { <br />
record();<br />
play();<br />
}<br />
}</source><br />
<br />
== 2. Abend ==<br />
<br />
Änderungen des IR-Signals werden aufgezeichnet, und auch zeitlich ausgewertet. Messung ist jedoch relativ ungenau. Implementation von Timer / Counter fehlt.<br />
<br />
<source lang ="c"><br />
/* ################################### */<br />
/* # IR-Empfang # */<br />
/* # Von Gruppe 1 # */<br />
/* ################################### */<br />
/* # Done: IR-Signale chronologisch # */<br />
/* # aufzeichnen # */<br />
/* ################################### */<br />
/* # Todo: Counter / Timer einbauen # */<br />
/* ################################### */<br />
<br />
<br />
#include <avr/io.h><br />
#include <string.h><br />
#include <stdio.h><br />
#include <avr/pgmspace.h><br />
#include <util/delay.h><br />
#include "uart.h"<br />
<br />
int main(void)<br />
{<br />
int status = 0;<br />
int counter = 0;<br />
/* initialize serial uart */<br />
uart_init();<br />
<br />
/* configure irrx as input */<br />
DDRC &= ~_BV(PC3);<br />
<br />
/* init led pin as output */<br />
DDRD |= _BV(PD3);<br />
<br />
while(1) {<br />
counter++;<br />
for (int i = 0; i<10; i++)<br />
{<br />
_delay_us(10);<br />
}<br />
/* if ir rx is high, turn off led */<br />
if (PINC & _BV(PC3)) {<br />
// Kein IR<br />
PORTD &= ~_BV(PD3);<br />
if (status == 1)<br />
{<br />
uart_printf("Ir jetzt aus %u\n",counter);<br />
counter = 0;<br />
}<br />
status = 0;<br />
<br />
} else {<br />
PORTD |= _BV(PD3);<br />
if (status == 0)<br />
{<br />
uart_printf("Ir jetzt an %u\n",counter);<br />
counter = 0;<br />
}<br />
status = 1;<br />
}<br />
}<br />
}<br />
</source><br />
<br />
== 3. Abend ==<br />
=== IR-Jammer ===<br />
Sendet, sobald er IR empfängt, für 1000ms und wartet dann 5ms, damit er das ausgesandte Signal nicht wieder empfängt.<br />
<br />
<source lang="c"><br />
#include <avr/io.h><br />
#include <avr/interrupt.h><br />
#include <util/delay.h><br />
#include "uart.h"<br />
<br />
/* constants */<br />
#define MAX 160<br />
/* 38khz: freq = F_CPU/(2*prescaler*frequency)<br />
* 20mhz/(2*8*38khz) = ~33<br />
* real frequency: 20mhz/(2*8*33) = ~37878Hz */<br />
#define PWM_FREQ 33<br />
<br />
/* global variables */<br />
<br />
/* allocate 160*2 = 320 byte memory for storing a code,<br />
* this means we can store 80 on/off sequence timings */<br />
volatile uint16_t code[MAX];<br />
/* current index in code[] (default: 0) */<br />
volatile uint8_t pos = 0;<br />
/* current pin state (default: high == idle) */<br />
volatile uint8_t state = 1;<br />
/* signal for the main application that a code has been received<br />
* (default: 0) */<br />
volatile uint8_t done = 0;<br />
/* signal button presses from interrupt to main */<br />
volatile uint8_t button_press;<br />
/* current system mode */<br />
enum {<br />
MODE_OFF = 0,<br />
MODE_DISPLAY = 1,<br />
MODE_JAM = 2,<br />
MODE_RECORD = 3,<br />
} mode = MODE_DISPLAY;<br />
/* current viewmode */<br />
enum {<br />
VIEW_VALUE_AND_TIME = 0,<br />
VIEW_VALUE = 1,<br />
VIEW_TIME = 2,<br />
} view = VIEW_VALUE_AND_TIME;<br />
<br />
/* call every 10 ms, for buttons at pins PC0-PC3 */<br />
static uint8_t button_sample(void)<br />
{<br />
/* initialize state, buttons are active low! */<br />
static uint8_t btn_state = 15; //0b1111;<br />
/* initialize old sample */<br />
static uint8_t last_sample = 15; //0b1111;<br />
/* read inputs */<br />
uint8_t new_sample = PINC & 15; //0b1111;<br />
<br />
/* mark bits which are sampled with the same value */<br />
uint8_t same_sample = (last_sample ^ ~new_sample);<br />
/* all bits set in same_sample now have been sampled with the same value<br />
* at least two times, which means the button has settled */<br />
<br />
/* compare the current button state with the most recent sampled value,<br />
* but only for those bits which have stayed the same */<br />
uint8_t state_different = btn_state ^ (new_sample & same_sample);<br />
/* all bits set in state_different have been sampled at least two times<br />
* with the same value, and this value is different from the current<br />
* button state */<br />
<br />
/* if a bit is set in state (means: button is not pressed) AND bit is set<br />
* in state_different (means: input has settled and value is different<br />
* from state) together means: button has been pressed recently */<br />
uint8_t btn_press = btn_state & state_different;<br />
<br />
/* toggle all bits for inputs which switched state */<br />
btn_state ^= state_different;<br />
<br />
/* store current sample for next time */<br />
last_sample = new_sample;<br />
<br />
/* if bit is set in btn_press, a button has been pressed<br />
* (not released yet) */<br />
return btn_press;<br />
}<br />
<br />
void wait(uint32_t s) {<br />
uint32_t i;<br />
for (i = 0; i < s; i++) {<br />
_delay_ms(1);<br />
}<br />
}<br />
<br />
/* set up timer 0 to generate a carrier using pwm at freq on pin OC0B (PD5) */<br />
static void ir_enable(uint8_t freq) {<br />
/* timer 0: fast pwm mode, clear OC0B on match, prescaler 8 */<br />
TCCR0A = _BV(WGM00) | _BV(COM0B1);<br />
TCCR0B = _BV(CS01) | _BV(WGM02);<br />
<br />
/* set frequency */<br />
OCR0A = freq;<br />
<br />
/* set duty-cycle to 50% */<br />
OCR0B = freq/2;<br />
}<br />
<br />
/* disable timer 0 and pwm generation */<br />
static void ir_disable(void) {<br />
TCCR0A = 0;<br />
TCCR0B = 0;<br />
}<br />
<br />
<br />
/* pin change interrupt 1 service function */<br />
ISR(PCINT1_vect)<br />
{<br />
/* do nothing if we are just processing a code in the main loop,<br />
* or no more space is available for a timer value */<br />
if (done || pos == MAX)<br />
return;<br />
<br />
/* if this would be the first timing value ever recorded, and the<br />
* state before was high (=idle), do not record the timing value<br />
* and just reset the timer */<br />
if (state && pos == 0) {<br />
TCNT1 = 0;<br />
/* else record the timing value */<br />
} else {<br />
/* store current timer value in code[]<br />
* and reset the timer */<br />
code[pos++] = TCNT1;<br />
TCNT1 = 0;<br />
}<br />
<br />
/* toggle second led */<br />
PORTD ^= _BV(PD3);<br />
<br />
/* toggle state */<br />
state = !state;<br />
}<br />
<br />
/* timer 1 compare A interrupt service function */<br />
ISR(TIMER1_COMPA_vect)<br />
{<br />
/* do nothing if we are just processing a code in the main loop */<br />
if (done)<br />
return;<br />
<br />
/* if some code has been received */<br />
if (pos > 0) {<br />
/* if pos is odd, one last 'off'-timing is missing, fill with zero */<br />
if (pos % 2 == 1)<br />
code[pos++] = 0;<br />
<br />
/* signal main */<br />
done = 1;<br />
<br />
/* turn on third led */<br />
PORTD |= _BV(PD6);<br />
}<br />
}<br />
<br />
/* timer 2 compare A interrupt service function */<br />
ISR(TIMER2_COMPA_vect)<br />
{<br />
/* sample buttons every 10ms */<br />
button_press |= button_sample();<br />
}<br />
<br />
int main(void)<br />
{<br />
/* initialize uart */<br />
uart_init();<br />
uart_printf("rumpus ir analyzer\n");<br />
<br />
/* configure led pins as outputs and turn leds off */<br />
DDRC |= _BV(PC4);<br />
DDRD |= _BV(PD3) | _BV(PD6) | _BV(PD7);<br />
PORTC &= ~_BV(PC4);<br />
PORTD &= ~(_BV(PD3) | _BV(PD6) | _BV(PD7));<br />
<br />
/* configure ir input pin, with pullup */<br />
DDRC &= ~_BV(PC3);<br />
PORTC |= _BV(PC3);<br />
<br />
/* configure button input pins, with pullup */<br />
DDRC &= ~(_BV(PC0) | _BV(PC1) | _BV(PC2) | _BV(PC3));<br />
PORTC |= _BV(PC0) | _BV(PC1) | _BV(PC2) | _BV(PC3);<br />
<br />
/* configure ir send pin as output, set low */<br />
DDRD |= _BV(PD5);<br />
PORTD &= ~_BV(PD5);<br />
<br />
/* wait until pin is high (no ir carrier is detected) */<br />
while(!(PINC & _BV(PC3)));<br />
<br />
/* enable pin change interrupt 1 for ir input pin (PC3/PCINT11) */<br />
PCMSK1 |= _BV(PCINT11);<br />
PCICR |= _BV(PCIE1);<br />
<br />
/* configure timer1 with prescaler 64 and CTC for measuring ir timings */<br />
TCCR1B = _BV(CS11) | _BV(CS10) | _BV(WGM12);<br />
/* configure timer action after 200ms: 20mhz/64/5 */<br />
OCR1A = F_CPU/5/64;<br />
/* enable OCR1A interrupt */<br />
TIMSK1 = _BV(OCIE1A);<br />
<br />
/* configure timer 2 with prescaler 1024 and CTC<br />
* for button sampling */<br />
TCCR2A = _BV(WGM21);<br />
TCCR2B = _BV(CS22) | _BV(CS21) | _BV(CS20);<br />
/* configure compare event a to occur after 10ms and enable interrupt */<br />
OCR2A = F_CPU/1024/100;<br />
TIMSK2 = _BV(OCIE2A);<br />
<br />
/* signal user availability by turning on led 1 */<br />
PORTC |= _BV(PC4);<br />
<br />
/* enable interrupts */<br />
sei();<br />
<br />
/* signal the user that the analyzer part has started by turning led 1 on */<br />
PORTC |= _BV(PC3);<br />
<br />
while(1) {<br />
/* if a code has been received */<br />
if (mode == MODE_DISPLAY && done) {<br />
<br />
/* print code to serial uart */<br />
uart_printf("complete code received, %u on-off-timings:\n", pos/2);<br />
for (uint8_t i = 0; i < pos; i += 2) {<br />
<br />
if (view == VIEW_VALUE_AND_TIME) {<br />
uint32_t on, off;<br />
<br />
/* compute timing in microseconds */<br />
on = ((uint32_t)code[i]) * 64 / 20;<br />
off = ((uint32_t)code[i+1]) * 64 / 20;<br />
<br />
uart_printf(" %5lu us (%5u) on, %5lu us (%5u) off\n",<br />
on, code[i],<br />
off, code[i+1]);<br />
} else if (view == VIEW_VALUE) {<br />
uart_printf(" %5u on, %5u off\n",<br />
code[i], code[i+1]);<br />
} else if (view == VIEW_TIME) {<br />
uint32_t on, off;<br />
<br />
/* compute timing in microseconds */<br />
on = ((uint32_t)code[i]) * 64 / 20;<br />
off = ((uint32_t)code[i+1]) * 64 / 20;<br />
<br />
uart_printf(" %5lu us on, %5lu us off\n",<br />
on, off);<br />
}<br />
}<br />
<br />
<br />
/* turn off second and third led */<br />
PORTD &= ~(_BV(PD3) | _BV(PD6));<br />
<br />
/* wait until pin is high (no ir carrier is detected) */<br />
while(!(PINC & _BV(PC3)));<br />
<br />
/* reset all global variables */<br />
pos = 0;<br />
state = 1;<br />
done = 0;<br />
}<br />
<br />
if (mode == MODE_JAM) {<br />
// hier wird gejammt!<br />
<br />
if (!state) {<br />
DDRC |= _BV(PC3); // ir empfang aus<br />
<br />
ir_enable(PWM_FREQ);<br />
wait(1000);<br />
ir_disable();<br />
<br />
wait(5); // damit wir unser eben gesendetes signal nicht empfangen<br />
DDRC &= ~_BV(PC3); // ir empfang an<br />
<br />
done = 0;<br />
pos = 0;<br />
}<br />
}<br />
<br />
if (button_press) {<br />
/* first button toggles system mode */<br />
if (button_press & 1) {<br />
mode++;<br />
if (mode > MODE_RECORD)<br />
mode = MODE_OFF;<br />
<br />
if (mode == MODE_OFF) {<br />
uart_printf("ir analyzer switched off\n");<br />
<br />
/* disable timer1 and pin change interrupts */<br />
TIMSK1 &= ~_BV(OCIE1A);<br />
PCMSK1 &= ~_BV(PCINT11);<br />
<br />
/* turn off led1 */<br />
PORTC &= ~_BV(PC4);<br />
<br />
} else if (mode == MODE_DISPLAY) {<br />
uart_printf("scan and display codes\n");<br />
<br />
/* clear interrupt flags, enable timer1 and pin change interrupts */<br />
TIFR1 = _BV(OCIE1A);<br />
TIMSK1 |= _BV(OCIE1A);<br />
PCMSK1 |= _BV(PCINT11);<br />
<br />
/* turn on led1 */<br />
PORTC |= _BV(PC4);<br />
} else if (mode == MODE_JAM) {<br />
/* clear interrupt flags, enable timer1 and pin change interrupts */<br />
TIFR1 = _BV(OCIE1A);<br />
TIMSK1 |= _BV(OCIE1A);<br />
PCMSK1 |= _BV(PCINT11);<br />
<br />
uart_printf("jamming mode active\n");<br />
} else if (mode == MODE_RECORD) {<br />
uart_printf("record and replay a code\n");<br />
}<br />
}<br />
<br />
<br />
/* second button toggles view mode */<br />
if (button_press & 2) {<br />
view++;<br />
if (view > VIEW_TIME)<br />
view = VIEW_VALUE_AND_TIME;<br />
<br />
if (view == VIEW_VALUE_AND_TIME)<br />
uart_printf("display timer value and time (in us)\n");<br />
else if (view == VIEW_VALUE)<br />
uart_printf("display timer value\n");<br />
else if (view == VIEW_TIME)<br />
uart_printf("display time (in us)\n");<br />
}<br />
<br />
if (button_press & 4) {<br />
static uint8_t pwm = 0;<br />
<br />
if (!pwm) {<br />
ir_enable(PWM_FREQ);<br />
uart_printf("pwm on\n");<br />
} else {<br />
ir_disable();<br />
uart_printf("pwm off\n");<br />
}<br />
pwm = !pwm;<br />
}<br />
<br />
button_press = 0;<br />
}<br />
}<br />
}</source><br />
[[Category:U23 2008]]</div>
Hendi
https://wiki.koeln.ccc.de/index.php?title=U23_2008-2/Feedback_Abend_1&diff=14584
U23 2008-2/Feedback Abend 1
2008-10-26T18:50:37Z
<p>Hendi: </p>
<hr />
<div>Ich mach mal einfach den Anfang, scheint sich ja keiner zu trauen :-). Mir hat der Abend Lust auf mehr gemacht! Ich hab mir erstmal ein C-Buch was hier noch rumgammelt geschnappt und bin so hoffentlich für das Kommende gewappnet. Für mich hat das Tempo der Erläuterungen gepasst. Ich bin auch über den Themenwechsel nicht traurig, wenn man tiefer gehen will, findet man sicher Möglichkeiten.<br />Bis nächsten Montag, ich brauche mehr Input!<br />''Christoph''<br />
<br /><br />
<br />
Ich wollt auch nur schnell sagen, dass ich die Themenauswahl bei der 2. Inkarnation cooler find, als bei der ersten. Ich wollt sowieso mal mit dem IR-Kram spielen, hatte ein Wochenende vorher schon angefangen mich damit mal in der Theorie auseinanderzusetzen, zu mehr bin ich aber leider nicht gekommen.<br /><br />
Tempo war OK, da ich das meiste schon kannte.<br /><br />
Andreas<br />
<br />
Ich bin auch der Meinung, dass die Themenwahl gelungen ist und das Tempo ist auch OK. Auf den IR-Kram freu ich mich auch schon.<br /><br />
Christian<br />
<br />
Mich hat der erste Abend dazu motiviert, mein altes myAVR-Board wieder rauszukramen und LEDs zum Blinken zu bringen. Es hat sich schon allein deswegen gelohnt, dass ich von dem Makro _BV() und der Funktion _delay_ms() erfahren habe :) Der Themenwechsel ist mir eigentlich wurscht da mich beides interessiert. Infrarot ist sicherlich einfacher und führt schneller zu Ergebnissen und macht dann hoffentlich Lust auf mehr! [[User:Hendi|Hendi]]<br />
<br />
[[Category:U23 2008]]</div>
Hendi