1 // license:GPL-2.0+
2 // copyright-holders:Felipe Sanches
3 /*
4     Replicator 1 desktop 3d printer
5 
6     driver by Felipe Correa da Silva Sanches <fsanches@metamaquina.com.br>
7 
8     Changelog:
9 
10     2013 DEC 28 [Felipe Sanches]:
11         * LCD now works. We can see the firmware boot screen :-)
12 
13     2013 DEC 24 [Felipe Sanches]:
14         * declaration of internal EEPROM
15 
16     2013 DEC 18 [Felipe Sanches]:
17         * Initial driver skeleton
18 */
19 
20 // TODO:
21 // * figure out what's wrong with the keypad inputs (interface seems to be blocked in the first screen)
22 // * fix avr8 timer/counter #0 (toggle OC0B) and #5 (overflow interrupt "Microsecond timer") so that we get the buzzer to work
23 // * figure-out correct size of internal EEPROM
24 // * emulate an SD Card
25 // * implement avr8 WDR (watchdog reset) opcode
26 
27 #include "emu.h"
28 #include "cpu/avr8/avr8.h"
29 #include "sound/dac.h"
30 #include "video/hd44780.h"
31 #include "emupal.h"
32 #include "screen.h"
33 #include "speaker.h"
34 
35 #define MASTER_CLOCK    16000000
36 #define LOG_PORTS 0
37 
38 //Port A bits:
39 //Bit 0 unused
40 //Bit 1 unused
41 #define A_AXIS_DIR (1 << 2)
42 #define A_AXIS_STEP (1 << 3)
43 #define A_AXIS_EN (1 << 4)
44 #define A_AXIS_POT (1 << 5)
45 #define B_AXIS_DIR (1 << 6)
46 #define B_AXIS_STEP (1 << 7)
47 
48 //Port B bits:
49 #define SD_CS (1 << 0)
50 #define SCK_1280 (1 << 1)
51 #define MOSI_1280 (1 << 2)
52 #define MISO_1280 (1 << 3)
53 #define EX2_PWR_CHECK (1 << 4)
54 #define EX2_HEAT (1 << 5)
55 #define EX2_FAN (1 << 6)
56 #define BLINK (1 << 7)
57 
58 //Port C bits:
59 #define EX2_1280 (1 << 0)
60 #define EX1_1280 (1 << 1)
61 #define LCD_CLK (1 << 2)
62 #define LCD_DATA (1 << 3)
63 #define LCD_STROBE (1 << 4)
64 #define RLED (1 << 5)
65 #define GLED (1 << 6)
66 #define DETECT (1 << 7)
67 
68 //Port D bits:
69 #define PORTD_SCL (1 << 0)
70 #define PORTD_SDA (1 << 1)
71 #define EX_RX_1280 (1 << 2)
72 #define EX_TX_1280 (1 << 3)
73 //Bit 4 unused
74 //Bit 5 unused
75 //Bit 6 unused
76 //Bit 7 unused
77 
78 //Port E bits:
79 #define RX_1280 (1 << 0)
80 #define TX_1280 (1 << 1)
81 #define THERMO_SCK (1 << 2)
82 #define THERMO_CS1 (1 << 3)
83 #define THERMO_CS2 (1 << 4)
84 #define THERMO_DO (1 << 5)
85 //Bit 6 unused
86 //Bit 7 unused
87 
88 //Port F bits:
89 #define X_AXIS_DIR (1 << 0)
90 #define X_AXIS_STEP (1 << 1)
91 #define X_AXIS_EN (1 << 2)
92 #define X_AXIS_POT (1 << 3)
93 #define Y_AXIS_DIR (1 << 4)
94 #define Y_AXIS_STEP (1 << 5)
95 #define Y_AXIS_EN (1 << 6)
96 #define Y_AXIS_POT (1 << 7)
97 
98 //Port G bits:
99 #define EX4_1280 (1 << 0)
100 #define EX3_1280 (1 << 1)
101 #define B_AXIS_EN (1 << 2)
102 //Bit 3 unused
103 #define CUTOFF_SR_CHECK (1 << 4)
104 #define BUZZ (1 << 5)
105 //Bit 6 unused
106 //Bit 7 unused
107 
108 //Port H bits:
109 #define CUTOFF_TEST (1 << 0)
110 #define CUTOFF_RESET (1 << 1)
111 #define EX1_PWR_CHECK (1 << 2)
112 #define EX1_HEAT (1 << 3)
113 #define EX1_FAN (1 << 4)
114 #define SD_WP (1 << 5)
115 #define SD_CD (1 << 6)
116 //Bit 7 unused
117 
118 //Port J bits:
119 #define BUTTON_CENTER (1 << 0)
120 #define BUTTON_RIGHT (1 << 1)
121 #define BUTTON_LEFT (1 << 2)
122 #define BUTTON_DOWN (1 << 3)
123 #define BUTTON_UP (1 << 4)
124 #define POTS_SCL (1 << 5)
125 #define B_AXIS_POT (1 << 6)
126 //Bit 7 unused
127 
128 //Port K bits:
129 #define Z_AXIS_DIR (1 << 0)
130 #define Z_AXIS_STEP (1 << 1)
131 #define Z_AXIS_EN (1 << 2)
132 #define Z_AXIS_POT (1 << 3)
133 #define EX7_1280 (1 << 4)
134 #define EX6_1280 (1 << 5)
135 #define EX5_1280 (1 << 6)
136 #define HBP_THERM (1 << 7)
137 
138 //Port L bits:
139 #define X_MIN (1 << 0)
140 #define X_MAX (1 << 1)
141 #define Y_MIN (1 << 2)
142 #define Y_MAX (1 << 3)
143 #define HBP (1 << 4)
144 #define EXTRA_FET (1 << 5)
145 #define Z_MIN (1 << 6)
146 #define Z_MAX (1 << 7)
147 
148 /****************************************************\
149 * I/O devices                                        *
150 \****************************************************/
151 
152 class replicator_state : public driver_device
153 {
154 public:
replicator_state(const machine_config & mconfig,device_type type,const char * tag)155 	replicator_state(const machine_config &mconfig, device_type type, const char *tag) :
156 		driver_device(mconfig, type, tag),
157 		m_maincpu(*this, "maincpu"),
158 		m_lcdc(*this, "hd44780"),
159 		m_dac(*this, "dac")
160 	{
161 	}
162 
163 	void replicator(machine_config &config);
164 
165 	void init_replicator();
166 
167 private:
168 	virtual void machine_start() override;
169 
170 	uint8_t m_port_a;
171 	uint8_t m_port_b;
172 	uint8_t m_port_c;
173 	uint8_t m_port_d;
174 	uint8_t m_port_e;
175 	uint8_t m_port_f;
176 	uint8_t m_port_g;
177 	uint8_t m_port_h;
178 	uint8_t m_port_j;
179 	uint8_t m_port_k;
180 	uint8_t m_port_l;
181 
182 	uint8_t shift_register_value;
183 
184 	required_device<avr8_device> m_maincpu;
185 	required_device<hd44780_device> m_lcdc;
186 	required_device<dac_bit_interface> m_dac;
187 
188 	uint8_t port_r(offs_t offset);
189 	void port_w(offs_t offset, uint8_t data);
190 	virtual void machine_reset() override;
191 	void replicator_palette(palette_device &palette) const;
192 	void replicator_data_map(address_map &map);
193 	void replicator_io_map(address_map &map);
194 	void replicator_prg_map(address_map &map);
195 };
196 
machine_start()197 void replicator_state::machine_start()
198 {
199 }
200 
port_r(offs_t offset)201 uint8_t replicator_state::port_r(offs_t offset)
202 {
203 	switch( offset )
204 	{
205 		case AVR8_IO_PORTA:
206 		{
207 #if LOG_PORTS
208 		printf("[%08X] Port A READ (A-axis signals + B-axis STEP&DIR)\n", m_maincpu->m_shifted_pc);
209 #endif
210 		return 0x00;
211 		}
212 		case AVR8_IO_PORTB:
213 		{
214 #if LOG_PORTS
215 		printf("[%08X] Port B READ (SD-CS; 1280-MISO/MOSI/SCK; EX2-FAN/HEAT/PWR-CHECK; BLINK)\n", m_maincpu->m_shifted_pc);
216 #endif
217 		return 0x00;
218 		}
219 		case AVR8_IO_PORTC:
220 		{
221 #if LOG_PORTS
222 		printf("[%08X] Port C READ (1280-EX1/EX2; LCD-signals; R&G-LED; DETECT)\n", m_maincpu->m_shifted_pc);
223 #endif
224 		return DETECT; //indicated that the Interface board is present.
225 		}
226 		case AVR8_IO_PORTD:
227 		{
228 #if LOG_PORTS
229 		printf("[%08X] Port D READ (SDA/SCL; 1280-EX-TX/RX)\n", m_maincpu->m_shifted_pc);
230 #endif
231 		return 0x00;
232 		}
233 		case AVR8_IO_PORTE:
234 		{
235 #if LOG_PORTS
236 		printf("[%08X] Port E READ (1280-TX/RX; THERMO-signals)\n", m_maincpu->m_shifted_pc);
237 #endif
238 		return 0x00;
239 		}
240 		case AVR8_IO_PORTF:
241 		{
242 #if LOG_PORTS
243 		printf("[%08X] Port F READ (X-axis & Y-axis signals)\n", m_maincpu->m_shifted_pc);
244 #endif
245 		return 0x00;
246 		}
247 		case AVR8_IO_PORTG:
248 		{
249 #if LOG_PORTS
250 		printf("[%08X] Port G READ (BUZZ; Cutoff-sr-check; B-axis EN; 1280-EX3/EX4)\n", m_maincpu->m_shifted_pc);
251 #endif
252 		return 0x00;
253 		}
254 		case AVR8_IO_PORTH:
255 		{
256 #if LOG_PORTS
257 		printf("[%08X] Port H READ (cuttoff-text/reset; EX1-FAN/HEAT/PWR-CHECK; SD-CD/SD-WP)\n", m_maincpu->m_shifted_pc);
258 #endif
259 		return 0x00;
260 		}
261 		case AVR8_IO_PORTJ:
262 		{
263 #if LOG_PORTS
264 		printf("[%08X] Port J READ (Interface buttons; POTS-SCL; B-axis-POT)\n", m_maincpu->m_shifted_pc);
265 #endif
266 		return ioport("keypad")->read();
267 		}
268 		case AVR8_IO_PORTK:
269 		{
270 #if LOG_PORTS
271 		printf("[%08X] Port K READ (Z-axis signals; HBP-THERM; 1280-EX5/6/7)\n", m_maincpu->m_shifted_pc);
272 #endif
273 		return 0x00;
274 		}
275 		case AVR8_IO_PORTL:
276 		{
277 #if LOG_PORTS
278 		printf("[%08X] Port L READ (HBP; EXTRA-FET; X-MIN/MAX; Y-MIN/MAX; Z-MIN/MAX)\n", m_maincpu->m_shifted_pc);
279 #endif
280 		return 0x00;
281 		}
282 	}
283 	return 0;
284 }
285 
port_w(offs_t offset,uint8_t data)286 void replicator_state::port_w(offs_t offset, uint8_t data)
287 {
288 	switch( offset )
289 	{
290 		case AVR8_IO_PORTA:
291 		{
292 			if (data == m_port_a) break;
293 #if LOG_PORTS
294 			uint8_t old_port_a = m_port_a;
295 			uint8_t changed = data ^ old_port_a;
296 
297 			printf("[%08X] ", m_maincpu->m_shifted_pc);
298 			if(changed & A_AXIS_DIR) printf("[A] A_AXIS_DIR: %s\n", data & A_AXIS_DIR ? "HIGH" : "LOW");
299 			if(changed & A_AXIS_STEP) printf("[A] A_AXIS_STEP: %s\n", data & A_AXIS_STEP ? "HIGH" : "LOW");
300 			if(changed & A_AXIS_EN) printf("[A] A_AXIS_EN: %s\n", data & A_AXIS_EN ? "HIGH" : "LOW");
301 			if(changed & A_AXIS_POT) printf("[A] A_AXIS_POT: %s\n", data & A_AXIS_POT ? "HIGH" : "LOW");
302 			if(changed & B_AXIS_DIR) printf("[A] B_AXIS_DIR: %s\n", data & B_AXIS_DIR ? "HIGH" : "LOW");
303 			if(changed & B_AXIS_STEP) printf("[A] B_AXIS_STEP: %s\n", data & B_AXIS_STEP ? "HIGH" : "LOW");
304 #endif
305 			m_port_a = data;
306 			break;
307 		}
308 		case AVR8_IO_PORTB:
309 		{
310 			if (data == m_port_b) break;
311 #if LOG_PORTS
312 			uint8_t old_port_b = m_port_b;
313 			uint8_t changed = data ^ old_port_b;
314 
315 			printf("[%08X] ", m_maincpu->m_shifted_pc);
316 			if(changed & SD_CS) printf("[B] SD Card Chip Select: %s\n", data & SD_CS ? "HIGH" : "LOW");
317 			if(changed & SCK_1280) printf("[B] 1280-SCK: %s\n", data & SCK_1280 ? "HIGH" : "LOW");
318 			if(changed & MOSI_1280) printf("[B] 1280-MOSI: %s\n", data & MOSI_1280 ? "HIGH" : "LOW");
319 			if(changed & MISO_1280) printf("[B] 1280-MISO: %s\n", data & MISO_1280 ? "HIGH" : "LOW");
320 			if(changed & EX2_PWR_CHECK) printf("[B] EX2-PWR-CHECK: %s\n", data & EX2_PWR_CHECK ? "HIGH" : "LOW");
321 			if(changed & EX2_HEAT) printf("[B] EX2_HEAT: %s\n", data & EX2_HEAT ? "HIGH" : "LOW");
322 			if(changed & EX2_FAN) printf("[B] EX2_FAN: %s\n", data & EX2_FAN ? "HIGH" : "LOW");
323 			if(changed & BLINK) printf("[B] BLINK: %s\n", data & BLINK ? "HIGH" : "LOW");
324 #endif
325 			m_port_b = data;
326 			break;
327 		}
328 		case AVR8_IO_PORTC:
329 		{
330 			if (data == m_port_c) break;
331 
332 			uint8_t old_port_c = m_port_c;
333 			uint8_t changed = data ^ old_port_c;
334 #if LOG_PORTS
335 			printf("[%08X] ", m_maincpu->m_shifted_pc);
336 			if(changed & EX2_1280) printf("[C] EX2_1280: %s\n", data & EX2_1280 ? "HIGH" : "LOW");
337 			if(changed & EX1_1280) printf("[C] EX1_1280: %s\n", data & EX1_1280 ? "HIGH" : "LOW");
338 			if(changed & LCD_CLK) printf("[C] LCD_CLK: %s\n", data & LCD_CLK ? "HIGH" : "LOW");
339 			if(changed & LCD_DATA) printf("[C] LCD_DATA: %s\n", data & LCD_DATA ? "HIGH" : "LOW");
340 			if(changed & LCD_STROBE) printf("[C] LCD_STROBE: %s\n", data & LCD_STROBE ? "HIGH" : "LOW");
341 			if(changed & RLED) printf("[C] RLED: %s\n", data & RLED ? "HIGH" : "LOW");
342 			if(changed & GLED) printf("[C] GLED: %s\n", data & GLED ? "HIGH" : "LOW");
343 			if(changed & DETECT) printf("[C] DETECT: %s\n", data & DETECT ? "HIGH" : "LOW");
344 #endif
345 			if (changed & LCD_CLK){
346 				/* The LCD is interfaced by an 8-bit shift register (74HC4094). */
347 				if (data & LCD_CLK){//CLK positive edge
348 					shift_register_value = (shift_register_value << 1) | ((data & LCD_DATA) >> 3);
349 					//printf("[%08X] ", m_maincpu->m_shifted_pc);
350 					//printf("[C] LCD CLK positive edge. shift_register=0x%02X\n", shift_register_value);
351 				}
352 			}
353 
354 			if(changed & LCD_STROBE){
355 				if (data & LCD_STROBE){ //STROBE positive edge
356 					logerror("LCD shift register = %02X\n", shift_register_value);
357 					m_lcdc->rs_w(BIT(shift_register_value, 1));
358 					m_lcdc->rw_w(BIT(shift_register_value, 2));
359 					m_lcdc->e_w(BIT(shift_register_value, 3));
360 					m_lcdc->db_w(shift_register_value & 0xF0);
361 				}
362 			}
363 			m_port_c = data;
364 
365 			break;
366 		}
367 		case AVR8_IO_PORTD:
368 		{
369 			if (data == m_port_d) break;
370 #if LOG_PORTS
371 			uint8_t old_port_d = m_port_d;
372 			uint8_t changed = data ^ old_port_d;
373 
374 			printf("[%08X] ", m_maincpu->m_shifted_pc);
375 			if(changed & PORTD_SCL) printf("[D] PORTD_SCL: %s\n", data & PORTD_SCL ? "HIGH" : "LOW");
376 			if(changed & PORTD_SDA) printf("[D] PORTD_SDA: %s\n", data & PORTD_SDA ? "HIGH" : "LOW");
377 			if(changed & EX_RX_1280) printf("[D] EX_RX_1280: %s\n", data & EX_RX_1280 ? "HIGH" : "LOW");
378 			if(changed & EX_TX_1280) printf("[D] EX_TX_1280: %s\n", data & EX_TX_1280 ? "HIGH" : "LOW");
379 #endif
380 			m_port_d = data;
381 			break;
382 		}
383 		case AVR8_IO_PORTE:
384 		{
385 			if (data == m_port_e) break;
386 #if LOG_PORTS
387 			uint8_t old_port_e = m_port_e;
388 			uint8_t changed = data ^ old_port_e;
389 
390 			printf("[%08X] ", m_maincpu->m_shifted_pc);
391 			if(changed & RX_1280) printf("[E] 1280-RX: %s\n", data & RX_1280 ? "HIGH" : "LOW");
392 			if(changed & TX_1280) printf("[E] 1280-TX: %s\n", data & TX_1280 ? "HIGH" : "LOW");
393 			if(changed & THERMO_SCK) printf("[E] THERMO-SCK: %s\n", data & THERMO_SCK ? "HIGH" : "LOW");
394 			if(changed & THERMO_CS1) printf("[E] THERMO-CS1: %s\n", data & THERMO_CS1 ? "HIGH" : "LOW");
395 			if(changed & THERMO_CS2) printf("[E] THERMO-CS2: %s\n", data & THERMO_CS2 ? "HIGH" : "LOW");
396 			if(changed & THERMO_DO) printf("[E] THERMO-DO: %s\n", data & THERMO_DO ? "HIGH" : "LOW");
397 #endif
398 			m_port_e = data;
399 			break;
400 		}
401 		case AVR8_IO_PORTF:
402 		{
403 			if (data == m_port_f) break;
404 #if LOG_PORTS
405 			uint8_t old_port_f = m_port_f;
406 			uint8_t changed = data ^ old_port_f;
407 
408 			printf("[%08X] ", m_maincpu->m_shifted_pc);
409 			if(changed & X_AXIS_DIR) printf("[F] X_AXIS_DIR: %s\n", data & X_AXIS_DIR ? "HIGH" : "LOW");
410 			if(changed & X_AXIS_STEP) printf("[F] X_AXIS_STEP: %s\n", data & X_AXIS_STEP ? "HIGH" : "LOW");
411 			if(changed & X_AXIS_EN) printf("[F] X_AXIS_EN: %s\n", data & X_AXIS_EN ? "HIGH" : "LOW");
412 			if(changed & X_AXIS_POT) printf("[F] X_AXIS_POT: %s\n", data & X_AXIS_POT ? "HIGH" : "LOW");
413 			if(changed & Y_AXIS_DIR) printf("[F] Y_AXIS_DIR: %s\n", data & Y_AXIS_DIR ? "HIGH" : "LOW");
414 			if(changed & Y_AXIS_STEP) printf("[F] Y_AXIS_STEP: %s\n", data & Y_AXIS_STEP ? "HIGH" : "LOW");
415 			if(changed & Y_AXIS_EN) printf("[F] Y_AXIS_EN: %s\n", data & Y_AXIS_EN ? "HIGH" : "LOW");
416 			if(changed & Y_AXIS_POT) printf("[F] Y_AXIS_POT: %s\n", data & Y_AXIS_POT ? "HIGH" : "LOW");
417 #endif
418 			m_port_f = data;
419 			break;
420 		}
421 		case AVR8_IO_PORTG:
422 		{
423 			if (data == m_port_g) break;
424 
425 			uint8_t old_port_g = m_port_g;
426 			uint8_t changed = data ^ old_port_g;
427 
428 #if LOG_PORTS
429 			printf("[%08X] ", m_maincpu->m_shifted_pc);
430 			if(changed & EX4_1280) printf("[G] EX4_1280: %s\n", data & EX4_1280 ? "HIGH" : "LOW");
431 			if(changed & EX3_1280) printf("[G] EX3_1280: %s\n", data & EX3_1280 ? "HIGH" : "LOW");
432 			if(changed & B_AXIS_EN) printf("[G] B_AXIS_EN: %s\n", data & B_AXIS_EN ? "HIGH" : "LOW");
433 			if(changed & CUTOFF_SR_CHECK) printf("[G] CUTOFF_SR_CHECK: %s\n", data & CUTOFF_SR_CHECK ? "HIGH" : "LOW");
434 			if(changed & BUZZ) printf("[G] BUZZ: %s\n", data & BUZZ ? "HIGH" : "LOW");
435 #endif
436 
437 			if (changed & BUZZ)
438 			{
439 				m_dac->write(BIT(data, 5));
440 			}
441 
442 			m_port_g = data;
443 			break;
444 		}
445 		case AVR8_IO_PORTH:
446 		{
447 			if (data == m_port_h) break;
448 #if LOG_PORTS
449 			uint8_t old_port_h = m_port_h;
450 			uint8_t changed = data ^ old_port_h;
451 
452 			printf("[%08X] ", m_maincpu->m_shifted_pc);
453 			if(changed & CUTOFF_TEST) printf("[H] CUTOFF_TEST: %s\n", data & CUTOFF_TEST ? "HIGH" : "LOW");
454 			if(changed & CUTOFF_RESET) printf("[H] CUTOFF_RESET: %s\n", data & CUTOFF_RESET ? "HIGH" : "LOW");
455 			if(changed & EX1_PWR_CHECK) printf("[H] EX1_PWR_CHECK: %s\n", data & EX1_PWR_CHECK ? "HIGH" : "LOW");
456 			if(changed & EX1_HEAT) printf("[H] EX1_HEAT: %s\n", data & EX1_HEAT ? "HIGH" : "LOW");
457 			if(changed & EX1_FAN) printf("[H] EX1_FAN: %s\n", data & EX1_FAN ? "HIGH" : "LOW");
458 			if(changed & SD_WP) printf("[H] SD_WP: %s\n", data & SD_WP ? "HIGH" : "LOW");
459 			if(changed & SD_CD) printf("[H] SD_CD: %s\n", data & SD_CD ? "HIGH" : "LOW");
460 #endif
461 			m_port_h = data;
462 			break;
463 		}
464 		case AVR8_IO_PORTJ:
465 		{
466 			if (data == m_port_j) break;
467 #if LOG_PORTS
468 			uint8_t old_port_j = m_port_j;
469 			uint8_t changed = data ^ old_port_j;
470 
471 			printf("[%08X] ", m_maincpu->m_shifted_pc);
472 			if(changed & BUTTON_CENTER) printf("[J] BUTTON_CENTER: %s\n", data & BUTTON_CENTER ? "HIGH" : "LOW");
473 			if(changed & BUTTON_RIGHT) printf("[J] BUTTON_RIGHT: %s\n", data & BUTTON_RIGHT ? "HIGH" : "LOW");
474 			if(changed & BUTTON_LEFT) printf("[J] BUTTON_LEFT: %s\n", data & BUTTON_LEFT ? "HIGH" : "LOW");
475 			if(changed & BUTTON_DOWN) printf("[J] BUTTON_DOWN: %s\n", data & BUTTON_DOWN ? "HIGH" : "LOW");
476 			if(changed & BUTTON_UP) printf("[J] BUTTON_UP: %s\n", data & BUTTON_UP ? "HIGH" : "LOW");
477 			if(changed & POTS_SCL) printf("[J] POTS_SCL: %s\n", data & POTS_SCL ? "HIGH" : "LOW");
478 			if(changed & B_AXIS_POT) printf("[J] B_AXIS_POT: %s\n", data & B_AXIS_POT ? "HIGH" : "LOW");
479 #endif
480 			m_port_j = data;
481 			break;
482 		}
483 		case AVR8_IO_PORTK:
484 		{
485 			if (data == m_port_k) break;
486 #if LOG_PORTS
487 			uint8_t old_port_k = m_port_k;
488 			uint8_t changed = data ^ old_port_k;
489 
490 			printf("[%08X] ", m_maincpu->m_shifted_pc);
491 			if(changed & Z_AXIS_DIR) printf("[K] Z_AXIS_DIR: %s\n", data & Z_AXIS_DIR ? "HIGH" : "LOW");
492 			if(changed & Z_AXIS_STEP) printf("[K] Z_AXIS_STEP: %s\n", data & Z_AXIS_STEP ? "HIGH" : "LOW");
493 			if(changed & Z_AXIS_EN) printf("[K] Z_AXIS_EN: %s\n", data & Z_AXIS_EN ? "HIGH" : "LOW");
494 			if(changed & Z_AXIS_POT) printf("[K] Z_AXIS_POT: %s\n", data & Z_AXIS_POT ? "HIGH" : "LOW");
495 			if(changed & EX7_1280) printf("[K] EX7_1280: %s\n", data & EX7_1280 ? "HIGH" : "LOW");
496 			if(changed & EX6_1280) printf("[K] EX6_1280: %s\n", data & EX6_1280 ? "HIGH" : "LOW");
497 			if(changed & EX5_1280) printf("[K] EX5_1280: %s\n", data & EX5_1280 ? "HIGH" : "LOW");
498 			if(changed & HBP_THERM) printf("[K] HBP_THERM: %s\n", data & HBP_THERM ? "HIGH" : "LOW");
499 #endif
500 			m_port_k = data;
501 			break;
502 		}
503 		case AVR8_IO_PORTL:
504 		{
505 			if (data == m_port_l) break;
506 #if LOG_PORTS
507 			uint8_t old_port_l = m_port_l;
508 			uint8_t changed = data ^ old_port_l;
509 
510 			printf("[%08X] ", m_maincpu->m_shifted_pc);
511 			if(changed & X_MIN) printf("[L] X_MIN: %s\n", data & X_MIN ? "HIGH" : "LOW");
512 			if(changed & X_MAX) printf("[L] X_MAX: %s\n", data & X_MAX ? "HIGH" : "LOW");
513 			if(changed & Y_MIN) printf("[L] Y_MIN: %s\n", data & Y_MIN ? "HIGH" : "LOW");
514 			if(changed & Y_MAX) printf("[L] Y_MAX: %s\n", data & Y_MAX ? "HIGH" : "LOW");
515 			if(changed & HBP) printf("[L] HBP: %s\n", data & HBP ? "HIGH" : "LOW");
516 			if(changed & EXTRA_FET) printf("[L] EXTRA_FET: %s\n", data & EXTRA_FET ? "HIGH" : "LOW");
517 			if(changed & Z_MIN) printf("[L] Z_MIN: %s\n", data & Z_MIN ? "HIGH" : "LOW");
518 			if(changed & Z_MAX) printf("[L] Z_MAX: %s\n", data & Z_MAX ? "HIGH" : "LOW");
519 #endif
520 			m_port_l = data;
521 			break;
522 		}
523 	}
524 }
525 
526 /****************************************************\
527 * Address maps                                       *
528 \****************************************************/
529 
replicator_prg_map(address_map & map)530 void replicator_state::replicator_prg_map(address_map &map)
531 {
532 	map(0x0000, 0x1FFFF).rom();
533 }
534 
replicator_data_map(address_map & map)535 void replicator_state::replicator_data_map(address_map &map)
536 {
537 	map(0x0200, 0x21FF).ram();  /* ATMEGA1280 Internal SRAM */
538 }
539 
replicator_io_map(address_map & map)540 void replicator_state::replicator_io_map(address_map &map)
541 {
542 	map(AVR8_IO_PORTA, AVR8_IO_PORTL).rw(FUNC(replicator_state::port_r), FUNC(replicator_state::port_w));
543 }
544 
545 /****************************************************\
546 * Input ports                                        *
547 \****************************************************/
548 
549 static INPUT_PORTS_START( replicator )
550 	PORT_START("keypad")
PORT_CODE(KEYCODE_M)551 	PORT_BIT(0x00000001, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("CENTER") PORT_CODE(KEYCODE_M)
552 	PORT_BIT(0x00000002, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("RIGHT") PORT_CODE(KEYCODE_D)
553 	PORT_BIT(0x00000004, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("LEFT") PORT_CODE(KEYCODE_A)
554 	PORT_BIT(0x00000008, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("DOWN") PORT_CODE(KEYCODE_S)
555 	PORT_BIT(0x00000010, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("UP") PORT_CODE(KEYCODE_W)
556 INPUT_PORTS_END
557 
558 /****************************************************\
559 * Machine definition                                 *
560 \****************************************************/
561 
562 void replicator_state::init_replicator()
563 {
564 }
565 
machine_reset()566 void replicator_state::machine_reset()
567 {
568 	shift_register_value = 0;
569 	m_port_a = 0;
570 	m_port_b = 0;
571 	m_port_c = 0;
572 	m_port_d = 0;
573 	m_port_e = 0;
574 	m_port_f = 0;
575 	m_port_g = 0;
576 	m_port_h = 0;
577 	m_port_j = 0;
578 	m_port_k = 0;
579 	m_port_l = 0;
580 }
581 
replicator_palette(palette_device & palette) const582 void replicator_state::replicator_palette(palette_device &palette) const
583 {
584 	// These colors were picked with the color picker in Inkscape, based on a photo of the LCD used in the Replicator 1 3d printer:
585 	palette.set_pen_color(0, rgb_t(0xca, 0xe7, 0xeb));
586 	palette.set_pen_color(1, rgb_t(0x78, 0xab, 0xa8));
587 }
588 
589 static const gfx_layout hd44780_charlayout =
590 {
591 	5, 8,                   /* 5 x 8 characters */
592 	256,                    /* 256 characters */
593 	1,                      /* 1 bits per pixel */
594 	{ 0 },                  /* no bitplanes */
595 	{ 3, 4, 5, 6, 7},
596 	{ 0, 8, 2*8, 3*8, 4*8, 5*8, 6*8, 7*8},
597 	8*8                     /* 8 bytes */
598 };
599 
600 static GFXDECODE_START( gfx_replicator )
601 	GFXDECODE_ENTRY( "hd44780:cgrom", 0x0000, hd44780_charlayout, 0, 1 )
602 GFXDECODE_END
603 
replicator(machine_config & config)604 void replicator_state::replicator(machine_config &config)
605 {
606 	ATMEGA1280(config, m_maincpu, MASTER_CLOCK);
607 	m_maincpu->set_addrmap(AS_PROGRAM, &replicator_state::replicator_prg_map);
608 	m_maincpu->set_addrmap(AS_DATA, &replicator_state::replicator_data_map);
609 	m_maincpu->set_addrmap(AS_IO, &replicator_state::replicator_io_map);
610 
611 	m_maincpu->set_eeprom_tag("eeprom");
612 	m_maincpu->set_low_fuses(0xff);
613 	m_maincpu->set_high_fuses(0xda);
614 	m_maincpu->set_extended_fuses(0xf4);
615 	m_maincpu->set_lock_bits(0x0f);
616 
617 	/*TODO: Add an ATMEGA8U2 for USB-Serial communications */
618 
619 	/* video hardware */
620 	screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_LCD));
621 	screen.set_refresh_hz(50);
622 	screen.set_vblank_time(ATTOSECONDS_IN_USEC(2500)); /* not accurate */
623 	screen.set_screen_update("hd44780", FUNC(hd44780_device::screen_update));
624 	screen.set_size(120, 18*2); //4x20 chars
625 	screen.set_visarea(0, 120-1, 0, 18*2-1);
626 	screen.set_palette("palette");
627 
628 	PALETTE(config, "palette", FUNC(replicator_state::replicator_palette), 2);
629 	GFXDECODE(config, "gfxdecode", "palette", gfx_replicator);
630 
631 	HD44780(config, "hd44780", 0).set_lcd_size(4, 20);
632 
633 	/* sound hardware */
634 	/* A piezo is connected to the PORT G bit 5 (OC0B pin driven by Timer/Counter #4) */
635 	SPEAKER(config, "speaker").front_center();
636 	DAC_1BIT(config, m_dac, 0).add_route(0, "speaker", 0.5);
637 }
638 
639 ROM_START( replica1 )
640 	ROM_REGION( 0x20000, "maincpu", 0 )
641 	ROM_DEFAULT_BIOS("v750")
642 
643 	/* Version 5.1 release:
644 	- Initial firmware release
645 	*/
646 	ROM_SYSTEM_BIOS( 0, "v51", "V 5.1" )
647 	ROMX_LOAD("mighty-mb40-v5.1.bin", 0x0000, 0x10b90, CRC(20d65cd1) SHA1(da18c3eb5a29a6bc1eecd92eaae6063fe29d0305), ROM_BIOS(0))
648 
649 	/* Version 5.2 release:
650 	- Nozzle Tolerance added to EEPROM
651 	- Updated onboard menus
652 	- X,Y calibration tool added
653 	*/
654 	ROM_SYSTEM_BIOS( 1, "v52", "V 5.2" )
655 	ROMX_LOAD("mighty-mb40-v5.2.bin", 0x0000, 0x126c4, CRC(555e47cf) SHA1(9d24a3dbeddce16669bb4d29c3366220ddf15d2a), ROM_BIOS(1))
656 
657 	/* Version 5.5 release:
658 	- Acceleration added to motor motion
659 	- Digipot updates
660 	*/
661 	ROM_SYSTEM_BIOS( 2, "v55", "V 5.5" )
662 	ROMX_LOAD("mighty-mb40-v5.5.bin", 0x0000, 0x1a420, CRC(9327d7e4) SHA1(d734ba2bda12f50ec3ac0035ab11591909d9edde), ROM_BIOS(2))
663 
664 	/* Version 6.2.0 release:
665 	- Bug fix release to firmware 6.0
666 	- Addresses wavy print issue above 1cm
667 	- Left extruder prints with makerware.
668 	*/
669 	ROM_SYSTEM_BIOS( 3, "v620", "V 6.2.0" )
670 	ROMX_LOAD("mighty_one_v6.2.0.bin", 0x0000, 0x1cf54, CRC(00df6f48) SHA1(db05afc2e1ebc104fb04753634a911187e396556), ROM_BIOS(3))
671 
672 	/* Version 7.0.0 release:
673 	- Major upgrade to Stepper Motor Smoothness (via Sailfish team)
674 	- X3G format introduced
675 	- Heaters default to leaving 'preheat' on more of the time
676 	*/
677 	ROM_SYSTEM_BIOS( 4, "v700", "V 7.0.0" )
678 	ROMX_LOAD("mighty_one_v7.0.0.bin", 0x0000, 0x1cb52, CRC(aa2a5fcf) SHA1(934e642b0b2d007689249680bad03c9255ae016a), ROM_BIOS(4))
679 
680 	/* Version 7.2.0 release:
681 	- Removes support for S3G files
682 	- X3G is the recognized format
683 	- Minor bug fixes
684 	*/
685 	ROM_SYSTEM_BIOS( 5, "v720", "V 7.2.0" )
686 	ROMX_LOAD("mighty_one_v7.2.0.bin", 0x0000, 0x1cb80, CRC(5e546706) SHA1(ed4aaf7522d5a5beea7eb69bf2c85d7a89f8f188), ROM_BIOS(5))
687 
688 	/* Version 7.3.0 release:
689 	- Pause at Z Height
690 	- Elapsed time displays during prints
691 	- Minor bug fixes
692 	*/
693 	ROM_SYSTEM_BIOS( 6, "v730", "V 7.3.0" )
694 	ROMX_LOAD("mighty_one_v7.3.0.bin", 0x0000, 0x1d738, CRC(71811ff5) SHA1(6728ea600ab3ff4b589adca90b0d700d9b70bd18), ROM_BIOS(6))
695 
696 	/* Version 7.4.0 (bugfix) release:
697 	- Fixes issues with Z Pause and elapsed print time
698 	*/
699 	ROM_SYSTEM_BIOS( 7, "v740", "V 7.4.0" )
700 	ROMX_LOAD("mighty_one_v7.4.0.bin", 0x0000, 0x1b9e2, CRC(97b05a27) SHA1(76ca2c9c1db2e006e501c3177a8a1aa693dda0f9), ROM_BIOS(7))
701 
702 	/* Version 7.5.0 (bugfix) release:
703 	- Fixes issue with Heat Hold
704 	*/
705 	ROM_SYSTEM_BIOS( 8, "v750", "V 7.5.0" )
706 	ROMX_LOAD("mighty_one_v7.5.0.bin", 0x0000, 0x1b9c4, CRC(169d6709) SHA1(62b5aacd1bc46969042aea7a50531ec467a4ff1f), ROM_BIOS(8))
707 
708 	/* Sailfish firmware image - Metam??quina experimental build v7.5.0 */
709 	ROM_SYSTEM_BIOS( 9, "v750mm", "V 7.5.0 - Metam??quina" )
710 	ROMX_LOAD("mighty_one_v7.5.0.mm.bin", 0x0000, 0x1ef9a, CRC(0d36d9e7) SHA1(a53899775b4c4eea87b6903758ebb75f06710a69), ROM_BIOS(9))
711 
712 
713 	/*Arduino MEGA bootloader */
714 	ROM_LOAD( "atmegaboot_168_atmega1280.bin", 0x1f000, 0x0f16, CRC(c041f8db) SHA1(d995ebf360a264cccacec65f6dc0c2257a3a9224) )
715 
716 	/* on-die 4kbyte eeprom */
717 	ROM_REGION( 0x1000, "eeprom", ROMREGION_ERASEFF )
718 ROM_END
719 
720 /*   YEAR  NAME      PARENT  COMPAT  MACHINE     INPUT       CLASS             INIT             COMPANY     FULLNAME */
721 COMP(2012, replica1, 0,      0,      replicator, replicator, replicator_state, init_replicator, "Makerbot", "Replicator 1 desktop 3d printer", MACHINE_NOT_WORKING)
722