вторник, 21 июня 2011 г.

AVR timers support

These modules implements for AVR8, AVR128, AVR168P chips next functions:
void init_timers(void);
int alarm_action(int timer, timer_handler_t alarm_handler);
int _alarm(int timer, unsigned long usec);
int alarm(int timer, unsigned long usec);
unsigned long tclock(int timer);
unsigned long millis(void);
unsigned long micros(void);
alarm() is like standard C function (but for AVR), it's wrapped by cli()/sei() _alarm(). int timer is the number of the used timer. tclock() is like C's clock() but used timer id. clock() is the tclock(0) - standard C function, implemented on timer 0. millis()/micros() returns milliseconds/microseconds from last call. Before use, call init_timer() first.

Before to use, define F_CPU. CLOCKS_PER_SEC should not be defined. If is, this means that some timer for clock() is already in use. Tested with WinAVR-20100110, but may be needs more testing!

You can download source code from here on Google Project page.

пятница, 10 июня 2011 г.

Software SPI implementation for WinAVR

Sometimes you need software SPI MASTER (in my case it was needed to test one chip) implementation. It supports all SPI modes (0, 1, 2, 3), and clock dividers (but so it's software "SPI", that timing is not exact!), but sends only in MSBFIRST bit order (it's easy to add LSBFIRST support).
See the code.
To use it in your project, you need to define some macro-variables (with #define-s) before include the file. They are:
  • SWSPI_MOSI_PORT - port for MOSI "wire"
  • SWSPI_MOSI_PIN - pin for MOSI "wire"
  • SWSPI_MISO_PORT - like above but for MISO (only port)
  • SWSPI_MISO_PIN - line above, but pin for MISO
  • SWSPI_SCLK_PORT - port for SCLK "wire"
  • SWSPI_SCLK_PIN - pin for SCLK "wire"
  • SWSPI_MODE - mode of SPI communication
  • SWSPI_DIV - if not defined, 1 will be used

The example:

#define SWSPI_MOSI_PORT PORTB
#define SWSPI_MOSI_PIN PB3
#define SWSPI_MISO_PORT PINB
#define SWSPI_MISO_PIN PB4
#define SWSPI_SCLK_PORT PORTB
#define SWSPI_SCLK_PIN PB5
#define SWSPI_MODE SPI_MODE0
#define SWSPI_DIV SPI_CLOCK_DIV2

In my real application I included .c file to local file in my project, it's not convenient way for C, but... seems like this:

common/   |  myprj/
swspi.h   |    conf.h (#include <common/swspi.h> and defines macro-vars)
swspi.h   |    spi.c (#include "conf.h" then #include <common/swspi.c>

You can use another scheme, it's trivial.
Here is the code. The .h file:

#ifndef _COMMON_SWSPI_H
#define _COMMON_SWSPI_H

#include <avr/io.h>
#include <util/delay.h>
#include <stdint.h>

#define SPI_CLOCK_DIV4 4
#define SPI_CLOCK_DIV16 16
#define SPI_CLOCK_DIV64 64
#define SPI_CLOCK_DIV128 128
#define SPI_CLOCK_DIV2 2
#define SPI_CLOCK_DIV8 8
#define SPI_CLOCK_DIV32 32
#define SPI_CLOCK_DIV64_2 64

#define SPI_MODE0 0
#define SPI_MODE1 1
#define SPI_MODE2 2
#define SPI_MODE3 3

uint8_t spi_transfer(uint8_t data);
uint8_t spi_ntransfer(const uint8_t *req, int reqlen, uint8_t *resp, int resplen);
#define spi_interrupt_on()
#define spi_interrupt_off()

// for nCS (nSEL) select of device before sending
#define BEGIN_SPI_SENDING(PORT, PIN) do { \
        (PORT) &= ~_BV(PIN); \
        _delay_loop_1(4); \
} while (0)

// for nCS (nSEL) unselect of device after sending
#define END_SPI_SENDING(PORT, PIN) do { \
        _delay_loop_1(4); \
        (PORT) |= _BV(PIN); \
} while (0)

#endif /* !_COMMON_SWSPI_H*/

and the .c file (swspi.c):

#include "swspi.h"
#include <util/delay_basic.h>

#if !defined(SWSPI_MOSI_PORT) || !defined(SWSPI_MOSI_PIN) || \
    !defined(SWSPI_MISO_PORT) || !defined(SWSPI_MISO_PIN) || \
    !defined(SWSPI_SCLK_PORT) || !defined(SWSPI_SCLK_PIN) || \
    !defined(SWSPI_MODE)
#  error Software SPI not configured! SWSPI_* should be configured!
#endif

#define setbit(P, B) ((P) |= (_BV(B)))
#define clibit(P, B) ((P) &= ~(_BV(B)))
#define getbit(P, B) (((P) & (_BV(B)))? 1:0)

#ifdef SWSPI_DIV
#  define SPIDELAYTIME ((SWSPI_DIV)/2)
#else
#  define SPIDELAYTIME 1
#endif
#define SPIHALFDELAY() _delay_loop_1(SPIDELAYTIME) // half of tact (bit transfer) - min 1 CPU tact

#define SETMOSI() setbit(SWSPI_MOSI_PORT, SWSPI_MOSI_PIN)
#define CLIMOSI() clibit(SWSPI_MOSI_PORT, SWSPI_MOSI_PIN)
#define NOMOSI() setbit(SWSPI_MOSI_PORT, SWSPI_MOSI_PIN)

// instead of PORTX may be PINX?
#define READMISO() getbit(SWSPI_MISO_PORT, SWSPI_MISO_PIN)

#if (2 & SWSPI_MODE)
#  define ONSCLK() clibit(SWSPI_SCLK_PORT, SWSPI_SCLK_PIN)
#  define OFFSCLK() setbit(SWSPI_SCLK_PORT, SWSPI_SCLK_PIN)
#else
#  define ONSCLK() setbit(SWSPI_SCLK_PORT, SWSPI_SCLK_PIN)
#  define OFFSCLK() clibit(SWSPI_SCLK_PORT, SWSPI_SCLK_PIN)
#endif

#if (1 & SWSPI_MODE)
#  define SHIFTBIT(outbyte, inbyte) do { \
        (outbyte) & 0x80 ? (SETMOSI()) : (CLIMOSI()); \
        (outbyte) <<= 1; \
        ONSCLK(); \
        SPIHALFDELAY(); \
        (inbyte) <<=1; \
        (inbyte) |= READMISO(); \
        OFFSCLK(); \
        SPIHALFDELAY(); \
} while (0)
#else
#  define SHIFTBIT(outbyte, inbyte) do { \
        (outbyte) & 0x80 ? (SETMOSI()) : (CLIMOSI()); \
        (outbyte) <<= 1; \
        SPIHALFDELAY(); \
        ONSCLK(); \
        SPIHALFDELAY(); \
        (inbyte) <<=1; \
        (inbyte) |= READMISO(); \
        OFFSCLK(); \
} while (0)
#endif

uint8_t
spi_transfer(uint8_t data) {
        int nbit;
        uint8_t res = 0;
        for (nbit=0; nbit<8; nbit++) {
                SHIFTBIT(data, res);
        }
        NOMOSI();
        return (res);
}

/* resp - responce from slave device; resplen - max. expected resp. len (buf. size);
 * if resp is NULL, not saved. Returns always the last byte of the response.
 */
uint8_t
spi_ntransfer(const uint8_t *req, int reqlen, uint8_t *resp, int resplen) {
        int nbit;
        int nbyte;
        register uint8_t outbyte;
        uint8_t inbyte = 0;
        for (nbyte=0; nbyte<reqlen; nbyte++) {
                outbyte = req[nbyte];
                inbyte = 0;
                for (nbit=0; nbit<8; nbit++) {
                        SHIFTBIT(outbyte, inbyte);
                }
                if (resp && nbyte < resplen) {
                        resp[nbyte] = inbyte;
                }
        }
        NOMOSI();
        return (inbyte);
}

#undef ONSCLK
#undef OFFSCLK
#undef SETMOSI
#undef CLIMOSI
#undef NOMOSI
#undef READMISO
#undef SPIHALFDELAY
#undef SPIDELAYTIME
#undef SHIFTBIT
#undef SHIFT0
To send and receive response spi_transfer() and spi_ntransfer() functions are needed. First sends one byte and returns responce's byte (from MISO), seconde - sends several bytes and saves them into 'resp' buffer (contrained by 'resplen') and if resp i NULL, returns the last byte only.
Before any transfer (one or several bytes in the one request) to some chip you should call macro BEGIN_SPI_SENDING(CHIP_NSEL_PORT, CHIP_NSEL_PIN), where CHIP_NSEL_PORT and CHIP_NSEL_PIN defines nCS wire for this concrete chip. After sending you should call END_SPI_SENDING(CHIP_NSEL_PORT, CHIP_NSEL_PIN) to release the wire by nCS.

понедельник, 6 июня 2011 г.

Another approach to Literate Programming

I tried for Literate Programming (LP) two solutions: Nuweb and Python tool Pyweb and found Pyweb tool is better. But with LP there are some problems:
  1. it's not very easy to work with "hidden" source: after tangling http://www.blogger.com/img/blank.gifand weaving you get pure source code and should debug source code (this is usually a "solid" process), after this - should modify .w file

  2. usage of "placeholders" lines split code (difficult for debugging)

Another approach is to use reStructuredText document generator system (see docutils). How to? It's easy: instead of embedding into source code the hyper-text formatting, images, links, you can write your program like story (in usual LP style), use RST syntax (like WiKi) for images embedding and various styles - your code is Literate Programming story as before. But now you can embed code fragments where you need with "include" directive of docutils. This directive requires "startd-after" and "end-before" options for this case. These options defines line (string fragment) the code starts after, and line - the code ends before. I use for this lines Vim foldering lines. See:
// Source code:
int x;
// Opening port {{{
int open_port(int port) {
...
}
// }}}

This is very usuable for folding big source code!
And in your .rst file (which plays a role of the .w file but for weaving only):
and we define the function for a port opening:

.. include:: port.c
:start-after: // Opening port {{{
:end-before: // }}}

Thos technique is not pure LP but is like LP without LP cons. And it's simple documentation approach :)

среда, 1 июня 2011 г.

Programming languages translated to C

There are:
  • ooc
  • BCX (it's Basic)
  • Nimrod
  • Eiffel
  • Scheme (shlep, Gambit-C, Bigloo, Chicken)
  • gcl (it's Common Lisp)
  • Virgil (it's Java-like)
  • Vala, Genie (from GNOME project)
  • Seed7 (Pascal-like)
  • Modula-2/Oberon-2
  • Mercury
and also there are translaters from Algol, Ada, Fortran, Pascal, Ada. Use Google to find it's repos :)