summaryrefslogtreecommitdiffstats
path: root/sw/programmer/avr/main.c
blob: 9cdc35d8e037262b2c08bd5278b293d4ab751e63 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
#include "usart.h"

#include <stdio.h>
#include <util/delay.h>

#define EEPROM_TICK_MS  10

#define ADDRCR      PORTB
#define EEPROMCR    PORTC
#define EEPROMDR    PORTD

#define ADDR_BIT    0
#define ADDR_EL     3
#define ADDR_EH     4
#define ADDR_DL     5
#define ADDR_DH     6

#define EEPROM_WR   0
#define EEPROM_RD   1
#define EEPROM_CLK  2

struct file_blk
{
    uint16_t addr;
    uint16_t size;
};

void eeprom_write(uint16_t addr, uint8_t byte);
void eeprom_tick();

int main(void)
{
    uint8_t *buffer, i;
    size_t read;
    char str[64];

    struct file_blk *blk = malloc(sizeof(struct file_blk));

    DDRB = 0x7F;
    DDRC = 0x83;
    DDRD = 0xFC;

    /* get configuration */
    usart_init(1200); 
    usart_print("programmer Ready\n<waiting for binary>\n\r");

    while (usart_read((uint8_t *) blk, sizeof(struct file_blk))) {
        buffer = malloc(blk->size);
        read = usart_read(buffer, blk->size);

#ifdef DEBUG
        sprintf(str, "info : reading block from addr %d of size %d\n\r", 
                blk->addr, blk->size);
        usart_print(str);

        if (read != blk->size) {
            sprintf(str, "error: expected %d but read %d\n\r", 
                    blk->size, read);
            usart_print(str);
        }
#endif

        for (i = 0; i < read; i++) {
            eeprom_write(blk->addr +i, buffer[i]);
        }

        free(buffer);
    }

    free(blk);
    return 0;
}


void eeprom_write(uint16_t addr, uint8_t byte)
{
    int bit;

    /* set address */
    for (bit = 0; bit < 8; bit++) {
        // clear bit
        ADDRCR &= ~0x07;
        // select the bit
        ADDRCR |= bit;

        // write bit for lower byte
        if (addr & _BV(bit))
            ADDRCR |= _BV(ADDR_DL);
        else
            ADDRCR &= ~_BV(ADDR_DL);

        // write bit for higher byte
        if ((addr>>8) & _BV(bit))
            ADDRCR |= _BV(ADDR_DH);
        else
            ADDRCR &= ~_BV(ADDR_DH);
    }

    /* set data */
    EEPROMDR = byte;
    EEPROMCR &= ~(_BV(ADDR_EH) | _BV(ADDR_EL));

    /* write eeprom */
    EEPROMCR &= ~_BV(EEPROM_WR);
    eeprom_tick();

    EEPROMCR |= _BV(EEPROM_WR);
    EEPROMCR |= _BV(ADDR_EH) | _BV(ADDR_EL);
}

/* pulse the clock line for the eeprom */
void eeprom_tick()
{
    EEPROMCR |= _BV(EEPROM_CLK);
    _delay_ms(EEPROM_TICK_MS);         
    EEPROMCR &= ~_BV(EEPROM_CLK);
    _delay_ms(EEPROM_TICK_MS);         
}