summaryrefslogtreecommitdiffstats
path: root/sw/programmer/avr/main.c
blob: e9fec62f9721b39d1dccf77e5a13dd7ea88e94f4 (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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
#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_set_addr(uint16_t addr);
void eeprom_write(uint16_t addr, uint8_t byte);
uint8_t eeprom_read(uint16_t addr);

int main(void)
{
    uint8_t *buffer, i;
    size_t read;

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

    DDRB = 0x7F;
    DDRC = 0x1F;
    DDRD = 0xFD;

    /* get configuration */
    usart_init(1200); 

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

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

        free(buffer);
        usart_send_byte(0x06);
        usart_send_byte(0x06);
        usart_send_byte(0x06);
    }

    free(blk);
    return 0;
}

void eeprom_set_addr(uint16_t addr)
{
    int bit;

    for (bit = 0; bit < 8; bit++) {
        // clear bits
        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);

        _delay_ms(5);
    }
}

void eeprom_write(uint16_t addr, uint8_t byte)
{
    eeprom_set_addr(addr);

    DDRC |= 0x18; // ED1 ED0
    DDRD |= 0xFC; // ED7-ED2

    /* set data */
    EEPROMDR = byte & 0xFC;

    // because EEPROMDR0 and EEPROMDR1 are used by Tx and Rx
    EEPROMCR = (PINC & 0xE7) | (byte & 0x03)<<3;

    /* enable address output */
    EEPROMCR &= ~(_BV(ADDR_EH) | _BV(ADDR_EL));

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

    /* reset */
    EEPROMCR |= _BV(EEPROM_WR);
    EEPROMCR |= _BV(ADDR_EH) | _BV(ADDR_EL);
}

uint8_t eeprom_read(uint16_t addr)
{
    uint8_t data;

    eeprom_set_addr(addr);

    DDRC &= ~0x18;
    DDRD &= ~0xFC;

    /* enable address output */
    EEPROMCR &= ~(_BV(ADDR_EH) | _BV(ADDR_EL));

    /* enable read eeprom */
    EEPROMCR &= ~_BV(EEPROM_RD);
    data = (PINC & 0x18) | (PIND & 0xFB);
    _delay_ms(5);

    /* reset */
    EEPROMCR |= _BV(EEPROM_RD);
    EEPROMCR |= _BV(ADDR_EH) | _BV(ADDR_EL);

    return data;
}