Mercurial > repos > blastem
comparison romdb.c @ 770:a3b90f746dcf
Broken EEPROM support
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Tue, 14 Jul 2015 18:28:05 -0700 |
parents | 4638b88bc72d |
children | 1b82b282b829 |
comparison
equal
deleted
inserted
replaced
769:4638b88bc72d | 770:a3b90f746dcf |
---|---|
14 #define RAM_FLAGS 0x1B2 | 14 #define RAM_FLAGS 0x1B2 |
15 #define RAM_START 0x1B4 | 15 #define RAM_START 0x1B4 |
16 #define RAM_END 0x1B8 | 16 #define RAM_END 0x1B8 |
17 #define REGION_START 0x1F0 | 17 #define REGION_START 0x1F0 |
18 | 18 |
19 void eeprom_init(eeprom_state *state) | 19 enum { |
20 I2C_IDLE, | |
21 I2C_START, | |
22 I2C_DEVICE_ACK, | |
23 I2C_ADDRESS_HI, | |
24 I2C_ADDRESS_HI_ACK, | |
25 I2C_ADDRESS, | |
26 I2C_ADDRESS_ACK, | |
27 I2C_READ, | |
28 I2C_READ_ACK, | |
29 I2C_WRITE, | |
30 I2C_WRITE_ACK | |
31 }; | |
32 | |
33 char * i2c_states[] = { | |
34 "idle", | |
35 "start", | |
36 "device ack", | |
37 "address hi", | |
38 "address hi ack", | |
39 "address", | |
40 "address ack", | |
41 "read", | |
42 "read_ack", | |
43 "write", | |
44 "write_ack" | |
45 }; | |
46 | |
47 void eeprom_init(eeprom_state *state, uint8_t *buffer, uint32_t size) | |
20 { | 48 { |
21 state->slave_sda = 1; | 49 state->slave_sda = 1; |
22 state->host_sda = state->scl = 0; | 50 state->host_sda = state->scl = 0; |
51 state->buffer = buffer; | |
52 state->size = size; | |
53 state->state = I2C_IDLE; | |
23 } | 54 } |
24 | 55 |
25 void set_host_sda(eeprom_state *state, uint8_t val) | 56 void set_host_sda(eeprom_state *state, uint8_t val) |
26 { | 57 { |
27 if (state->scl) { | 58 if (state->scl) { |
28 if (val & ~state->host_sda) { | 59 if (val & ~state->host_sda) { |
29 //stop condition | 60 //low to high, stop condition |
61 state->state = I2C_IDLE; | |
62 state->slave_sda = 1; | |
30 } else if (~val & state->host_sda) { | 63 } else if (~val & state->host_sda) { |
31 //start condition | 64 //high to low, start condition |
65 state->state = I2C_START; | |
66 state->slave_sda = 1; | |
67 state->counter = 8; | |
32 } | 68 } |
33 } | 69 } |
34 state->host_sda = val; | 70 state->host_sda = val; |
35 } | 71 } |
36 | 72 |
37 void set_scl(eeprom_state *state, uint8_t val) | 73 void set_scl(eeprom_state *state, uint8_t val) |
38 { | 74 { |
39 if (val & ~state->scl) { | 75 if (val & ~state->scl) { |
40 //latch sda | 76 //low to high transition |
77 switch (state->state) | |
78 { | |
79 case I2C_START: | |
80 case I2C_ADDRESS_HI: | |
81 case I2C_ADDRESS: | |
82 case I2C_WRITE: | |
83 state->latch = state->host_sda << 7 | state->latch >> 1; | |
84 state->counter--; | |
85 if (!state->counter) { | |
86 switch (state->state & 0x7F) | |
87 { | |
88 case I2C_START: | |
89 state->state = I2C_DEVICE_ACK; | |
90 break; | |
91 case I2C_ADDRESS_HI: | |
92 state->address = state->latch << 8; | |
93 state->state = I2C_ADDRESS_HI_ACK; | |
94 break; | |
95 case I2C_ADDRESS: | |
96 state->address |= state->latch; | |
97 state->state = I2C_ADDRESS_ACK; | |
98 break; | |
99 case I2C_WRITE: | |
100 state->buffer[state->address] = state->latch; | |
101 state->state = I2C_WRITE_ACK; | |
102 state->address++; | |
103 //TODO: page mask | |
104 state->address &= state->size-1; | |
105 break; | |
106 } | |
107 } | |
108 break; | |
109 case I2C_DEVICE_ACK: | |
110 if (state->latch & 1) { | |
111 state->state = I2C_READ; | |
112 state->counter = 8; | |
113 state->latch = state->buffer[state->address]; | |
114 state->address++; | |
115 //TODO: page mask | |
116 state->address &= state->size-1; | |
117 } else { | |
118 if (state->size < 256) { | |
119 state->address = state->latch >> 1; | |
120 state->state = I2C_WRITE; | |
121 } else if (state->size < 8192) { | |
122 state->address = state->latch << 8; | |
123 state->state = I2C_ADDRESS; | |
124 } else { | |
125 state->state = I2C_ADDRESS_HI; | |
126 } | |
127 state->counter = 8; | |
128 } | |
129 break; | |
130 case I2C_ADDRESS_HI_ACK: | |
131 state->state = I2C_ADDRESS; | |
132 break; | |
133 case I2C_ADDRESS_ACK: | |
134 state->state = I2C_WRITE; | |
135 break; | |
136 case I2C_READ: | |
137 state->counter--; | |
138 if (!state->counter) { | |
139 state->state = I2C_READ_ACK; | |
140 } | |
141 break; | |
142 case I2C_READ_ACK: | |
143 state->state = I2C_READ; | |
144 break; | |
145 case I2C_WRITE_ACK: | |
146 state->state = I2C_WRITE; | |
147 break; | |
148 } | |
149 } else if (~val & state->scl) { | |
150 //high to low transition | |
151 switch (state->state & 0x7F) | |
152 { | |
153 case I2C_DEVICE_ACK: | |
154 case I2C_ADDRESS_HI_ACK: | |
155 case I2C_ADDRESS_ACK: | |
156 case I2C_READ_ACK: | |
157 case I2C_WRITE_ACK: | |
158 state->slave_sda = 0; | |
159 break; | |
160 case I2C_READ: | |
161 state->slave_sda = state->latch >> 7; | |
162 state->latch = state->latch << 1; | |
163 break; | |
164 default: | |
165 state->slave_sda = 1; | |
166 break; | |
167 } | |
41 } | 168 } |
42 state->scl = val; | 169 state->scl = val; |
43 } | 170 } |
44 | 171 |
45 uint8_t get_sda(eeprom_state *state) | 172 uint8_t get_sda(eeprom_state *state) |
190 if (map->sda_write_mask) { | 317 if (map->sda_write_mask) { |
191 printf("sda: %d\n", (value & map->sda_write_mask) != 0); | 318 printf("sda: %d\n", (value & map->sda_write_mask) != 0); |
192 set_host_sda(&gen->eeprom, (value & map->sda_write_mask) != 0); | 319 set_host_sda(&gen->eeprom, (value & map->sda_write_mask) != 0); |
193 } | 320 } |
194 if (map->scl_mask) { | 321 if (map->scl_mask) { |
195 printf("scl: %d\n", (value & map->scl_mask) != 0); | 322 set_scl(&gen->eeprom, (value & map->scl_mask) != 0); |
196 set_scl(&gen->eeprom, (value & map->sda_write_mask) != 0); | 323 printf("scl: %d, state: %s, counter: %d\n", (value & map->scl_mask) != 0, i2c_states[gen->eeprom.state], gen->eeprom.counter); |
197 } | 324 } |
198 return context; | 325 return context; |
199 } | 326 } |
200 | 327 |
201 void * write_eeprom_i2c_b(uint32_t address, void * context, uint8_t value) | 328 void * write_eeprom_i2c_b(uint32_t address, void * context, uint8_t value) |
219 if (map->sda_write_mask & mask) { | 346 if (map->sda_write_mask & mask) { |
220 printf("sda: %d\n", (expanded & map->sda_write_mask) != 0); | 347 printf("sda: %d\n", (expanded & map->sda_write_mask) != 0); |
221 set_host_sda(&gen->eeprom, (expanded & map->sda_write_mask) != 0); | 348 set_host_sda(&gen->eeprom, (expanded & map->sda_write_mask) != 0); |
222 } | 349 } |
223 if (map->scl_mask & mask) { | 350 if (map->scl_mask & mask) { |
224 printf("scl: %d\n", (expanded & map->scl_mask) != 0); | 351 printf("scl: %d, state: %s\n", (expanded & map->scl_mask) != 0, i2c_states[gen->eeprom.state]); |
225 set_scl(&gen->eeprom, (expanded & map->scl_mask) != 0); | 352 set_scl(&gen->eeprom, (expanded & map->scl_mask) != 0); |
226 } | 353 } |
227 return context; | 354 return context; |
228 } | 355 } |
229 | 356 |