Code:
#include <AVR.h>
#include "ports.h"
#include "pattern.h"
#include <div.h>
#include "timer2.h"
#include "hell.h"
#include "timer1-job.h"
#include <avr/delay.h>
#include "menu.h"
pattern_t pat;
// Feste Muster für Ziffer 0=2, 1, 3
typedef uint16_t muster_t[3][10];
const muster_t m_wurfel PROGMEM = {
/*1*/ { 0x0, 0x8, 0x0c, 0x26, 0x33, 0x3b, 0x3f },
/*2,0*/ { 0x0, 0x10, 0x101, 0x54, 0x145, 0x155, 0x16d, 0x1d7, 0x1ef, 0x1ff },
/*3*/ { 0x0, 0x2, 0x5, 0x7 }
};
const muster_t m_fill PROGMEM = {
/*1*/ { 0x0, 0x1, 0x5, 0x15, 0x17, 0x1f, 0x3f },
/*2,0*/ { 0x0, 0x1, 0x9, 0x49, 0x4b, 0x5b, 0xdb, 0xdf, 0xff, 0x1ff },
/*3*/ { 0x0, 0x1, 0x3, 0x7 }
};
void pattern_out (uint8_t num)
{
pattern_t *p = &pat;
RELOAD ("b", p);
uint8_t off = 0;
uint8_t tick = p->pwm.tick;
uint8_t duty = p->pwm.duty;
uint8_t max = p->pwm.max;
uint8_t tnum = num >> 2;
p->rownum = num = num & 3;
if (0 == num)
{
tick++;
if (tick >= max)
tick = 0;
p->pwm.tick = tick;
}
if (tick >= duty)
off = 1;
if (hell.state == HS_MESS)
{
if (!off)
hell.mess_count++;
return; // TIMSK &= ~TIMSK_T1;
}
if (hell.state == HS_PREPARE_MESS)
{
hell_mess_start();
return;
}
// alles aus
SET_KATHODES;
// Gap durch SOFT-PWM
if (hell.state == HS_AWAIT_PATTERN_GAP
// hook in Anfang einer längeren off-Sequenz
&& num == 0 && tick == duty
// nur, wenn duty < 100%, redundant!
&& duty < max)
{
// 1 extra Gap zum relax der LEDs
if (tick == duty)
{
hell.state = HS_PREPARE_MESS;
MAKE_IN_ANODES;
CLR_ANODES;
SET (PORT_ANO1); MAKE_OUT (PORT_ANO1);
SET (PORT_ANO0); MAKE_OUT (PORT_ANO0);
SET (PORT_ANO2); //MAKE_OUT (PORT_ANO2);
CLR_KATHODES;
_delay_loop_1 (1);
SET_KATHODES;
return;
}
}
CLR_ANODES;
MAKE_IN_ANODES;
if (num == 3 && tnum <= 3)
{
/*3*/
/*7*/
/*11*/
/*15*/
// Gap durch MUX
return;
}
if (off && num < 3)
return;
// PullUps für Spalte4 (rote Spalte als Trenner)
if (num == 3)
{
if (tnum > 3 && (PM_BCD == p->mode))
{
tnum %= 4;
if (tnum < 3)
{
if (0 == tnum) { MAKE_IN (PORT_ANO0); SET (PORT_ANO0); }
if (1 == tnum) { MAKE_IN (PORT_ANO1); SET (PORT_ANO1); }
if (2 == tnum) { MAKE_IN (PORT_ANO2); SET (PORT_ANO2); }
CLR (PORT_KAT4);
}
}
return;
}
uint16_t bits = pat.row[num];
uint8_t pow2 = POW2 (num);
{ // Blinken
if (pat.blink_count >= 50)
if (pow2 & pat.blink_row)
bits &= ~pat.blink_mask;
}
uint8_t portc = bits;
if (0 == num) SET (PORT_ANO0);
if (0 == num) MAKE_OUT (PORT_ANO0);
BARRIER;
if (1 == num) SET (PORT_ANO1);
if (1 == num) MAKE_OUT (PORT_ANO1);
BARRIER;
if (2 == num) SET (PORT_ANO2);
if (2 == num) MAKE_OUT (PORT_ANO2);
BARRIER;
PORTC = ~0x1f | ~portc;
if (bits & (1<<5)) CLR (PORT_KAT5);
if (bits & (1<<6)) CLR (PORT_KAT6);
if (bits & (1<<7)) CLR (PORT_KAT7);
if (bits & (1<<8)) CLR (PORT_KAT8);
}
uint16_t set_n_bits0 (uint8_t total, uint8_t n)
{
return set_n_bits (total, n, 0);
}
// setzt n bits von total (rechts)
// 0 <= n <= total
// verwendet rndval[]
uint16_t set_n_bits (uint8_t total, uint8_t n, uint32_t quot /*rndval*/)
{
uint16_t val;
if (n > total)
n = total;
val = 0;
while (n != 0)
{
uint8_t pos;
// Constraint "e" forces quot into y,z
// Otherwise z has to be marked as clobbered (by udiv32)
__asm__ __volatile (
"movw r22, %A0" CR_TAB
"movw r24, %C0" CR_TAB
"mov r18, %3" CR_TAB
"clr r19" CR_TAB
"clr r20" CR_TAB
"clr r21" CR_TAB
"rcall __udivmodsi4" CR_TAB
"movw %A0, r18" CR_TAB
"movw %C0, r20" CR_TAB
"mov %1, r22"
: "=e" (quot), "=r" (pos) /* rem */
: "0" (quot), "r" (total)
: "r18", "r19", "r20", "r21",
"r22", "r23", "r24", "r25",
"r26", "r27"
);
uint16_t mask = 1;
// pos-tes freies Bit suchen
while (1)
{
if (!(val & mask))
if (pos-- == 0)
break;
mask <<= 1;
}
val |= mask;
total--;
n--;
}
return val;
}
/*
Bildet pat.bits[] ab auf pat.row[]
pat.bits[4]: Bitpattern der einzelnen Ziffern
pat.row[3]: Die 3 geMUXten Zeilen
Durch diese Anordnung der Bits werden nur gleichfarbige
LEDs gegeneinander gemultiplext.
8 765 43 210 set bits: pat.row[?]
3 222 11 000 pat.data[?]
2 876 54 876 pat.row[2]
1 543 32 543 pat.row[1]
0 210 10 210 pat.row[0]
# @@@ ** QQQ row 2
# @@@ ** QQQ row 1
# @@@ ** QQQ row 0
*/
uint16_t bits_to_row (uint8_t row)
{
pattern_t *pp = &pat;
RELOAD ("z", pp);
uint8_t val0 = pp->bits[0];
uint8_t val1 = pp->bits[1];
uint8_t val2 = pp->bits[2];
uint8_t val3 = pp->bits[3];
if (0 == row)
{
val1 <<= 3;
val2 <<= 5;
}
if (1 == row)
{
val0 >>= 3;
val1 <<= 1;
val2 <<= 2;
val3 >>= 1;
}
if (2 == row)
{
val0 = pp->bits[0] >> 1; val0 >>= 5;
val1 >>= 1;
val2 = pp->bits[2] >> 1;
val3 >>= 2;
}
val0 &= 7; // 000000111
val1 &= 3<<3; // 000011000
val2 &= 7<<5; // 011100000
uint16_t res = val0 | val1 | val2;
if (val3 & 1) // 100000000
res |= 0x100;
return res;
}
void digit_to_bits (uint8_t n, uint8_t max)
{
uint16_t wert;
uint8_t mask = POW2 (n);
uint8_t dig = pat.digit[n+2];
if (dig > max)
dig = max;
if (PM_WURFEL == pat.mode || PM_FILL == pat.mode)
{
// 1-->0 0,2-->1 3-->2
uint8_t idx = n-1;
if (idx >= 0x80)
idx = 1;
const muster_t * muster = & m_wurfel;
if (PM_FILL == pat.mode)
muster = & m_fill;
wert = pgm_read_word (& (*muster)[idx][dig]);
}
else if (PM_COLORS == pat.mode)
{
wert = 0;
if (pat.data[0] & mask) wert = 0xffff;
}
else //(PM_RANDOM == p->mode)
{
wert = set_n_bits (max, dig, pat.rand[n]);
}
pat.bits[n] = wert;
}
static uint16_t pattern_data_to_row_2434 (uint8_t data)
{
udiv8_t qrem = { .quot = data};
uint8_t j, shift = 0;
uint16_t row = 0;
for (j=0; j<4; j++)
{
uint8_t leds = 3;
if (j == 3) leds >>= 1;
if (j == 1) leds--;
qrem = udiv8 (qrem.quot, leds+1);
row |= set_n_bits0 (leds, qrem.rem) << shift;
shift += leds;
}
return row;
}
static uint16_t pattern_data_to_row_bin (uint8_t data)
{
uint16_t row = data;
uint8_t data3 = pat.data3;
if (data3 & 1)
row |= 0x100;
pat.data3 = (data3 >> 1);
return row;
}
void pattern_data_to_rows()
{
pattern_t * pp = &pat;
RELOAD ("y", pp);
uint16_t (*func) (uint8_t);
if (PM_BIN == pp->mode)
{
pp->data3 = pp->data[3];
func = pattern_data_to_row_bin;
goto _call_func;
}
if (PM_2434 == pp->mode)// || PM_BIN == pp->mode)
{
func = pattern_data_to_row_2434;
_call_func:;
pp->row2[0] = func (pp->data[0]);
pp->row2[1] = func (pp->data[1]);
pp->row2[2] = func (pp->data[2]);
goto _eiuhr;
}
{
udiv8_t qrem;
qrem = udiv8 (pp->data[0], 10); pp->digit[0] = qrem.rem; pp->digit[1] = qrem.quot;
qrem = udiv8 (pp->data[1], 10); pp->digit[2] = qrem.rem; pp->digit[3] = qrem.quot;
qrem = udiv8 (pp->data[2], 10); pp->digit[4] = qrem.rem; pp->digit[5] = qrem.quot;
}
if (PM_BCD == pp->mode) // || PM_BCD5 == pp->mode)
{
uint8_t i, * pdig = pp->digit;
for (i=0; i<=2; i++)
{
uint8_t dig0 = *pdig++;
uint8_t dig1 = *pdig++;
dig1 = swap (dig1);
pp->row2[i] = (dig1 << 1) | dig0;
}
}
else
{
digit_to_bits (0, 9);
digit_to_bits (1, 6);
digit_to_bits (2, 9);
digit_to_bits (3, 3);
pp->row2[0] = bits_to_row (0);
pp->row2[1] = bits_to_row (1);
pp->row2[2] = bits_to_row (2);
}
_eiuhr:;
#define BLINK_DAUER 15
uint16_t row0 = pp->row2[0];
uint8_t blink;
blink = count.ms10.eiuhr_blink-(50-BLINK_DAUER/5);
if (MID_MAIN == menu.id
&& menu.eiuhr.runs
&& blink < BLINK_DAUER)
{
row0 ^= 1;
}
pp->row[0] = row0;
pp->row[1] = pp->row2[1];
pp->row[2] = pp->row2[2];
}
Lesezeichen