Saturday, June 30, 2007

Farewell

I managed to finish firmware yesterday. Good!

Yesterday afternoon I had a long farewell lunch at the airport with our guest from France. He is a rather smart guy, who had been staying at the Institute for a month trying frantically to use our main product for real and succeeeding in that. Despite all the problems; including starting working week later than planned. I always felt that we were not treating him nicely because we had been busy doing other thing and not going out for lunch or giving him too little support using our products. However, much to my surprise he said that compared to his previous stay in German (three months) we were very friendly and supportive. In fact, he invited me to visit France and I promised to do so.

Beforehand I was very reluctant to spend some extra time, but now it looks like time well spent. Time spent with our clients is rarely time wasted.

Friday, June 29, 2007

Today I still have my hands at the same firmware I had on Monday. The spec is four pages long and I made an improvement today, which will be implemented tomorrow - FIVE DAYS LATER.

It is time to improve my spec-writing skills and reap the benefits of thinking before diving straight into the code.

Thursday, June 28, 2007

One-liner (almost) CRC.

Dallas iButton 8-bit CRC calculation.
Source: http://www.maxim-ic.com/appnotes.cfm/appnote_number/27
Polynomial: x^8 + x^5 + x^4 + 1 (0x8C)
Initial value: 0x00

uint8_t
_crc_ibutton_update(uint8_t crc, uint8_t data)
{
uint8_t i;
crc = crc ^ data;
for (i = 0; i < 8; ++i) {
crc = (crc << 1) ^ ((crc & 0x01) * 0x8C);
}
return crc;
}

64 bits and timers on AVR

Inclusion of 64-bit multiplication and division increases code size by 10 kilobytes on an AVR ATmega8. Reworked the formula to avoid uint64_t-s.

Timer-based stepper movement is just great. Compared to _delay_1 or _delay_ms it offers following benefits:

  • Frees CPU up for other tasks.
  • Delay lengths are can be easily specified in milli- or microseconds.

It's not hard. I prepare a list of 'actions' to execute beforehand and set the timer top as follows:
/** Set up timer 1 (16-bit), frequency = F_CPU/(timertop+1). */
#define setup_timer1(timertop) do { \
OCR1A = (timertop); /* set top */ \
/* Mode 4 - CTC with Prescaler 1 */ \
TCCR1B = (1<<WGM12)|(1<<CS10); \
TCNT1 = 0; /* reset counter */ \
TIMSK |= (1<<OCIE1A); /* enable output-compare int */ \
} while (0)

/**
* Calculate timertop for setup_timer1.
*/
static uint16_t
timertop_of( const uint16_t length,
const uint16_t time_ms)
{
const uint16_t timertop = (((uint32_t)time_ms) * (F_CPU/100) / 10) / length - 1;
return timertop;
}

/** Current action index. */
static int8_t action_index = -1;
/** Actions are executed from back to front. */
static ACTION actions[5];


The interrupt service routine chews through the list of actions:
SIGNAL(SIG_OUTPUT_COMPARE1A)
{
if (action_index>=0) {
ACTION* act = &actions[action_index];
move_1_step(act->step_direction);
if (--(act->countdown) == 0) {
--action_index;
}
}
}

The experienced reader can fill out the details...

Wednesday, June 27, 2007

ARM power consumption

ARM7TDMI core takes at least 15mA when running on 3.6864 MHz. AT91SAM7S256.