summaryrefslogtreecommitdiffstatshomepage
path: root/src/mame/drivers/candela.cpp
blob: 0f01b4ada1c29563315c7ca166d079ff8b5004c5 (plain) (blame)
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
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
// license:BSD-3-Clause
// copyright-holders:Joakim Larsson Edstrom
/*
 *
 * History of Candela Data AB
 *---------------------------
 * The Candela computer was designed to be the big breakthough and developed by Candela Data AB, "a Didact Company".
 * The Candela system was based around a main unit that could run OS-9 or Flex and a terminal unit that had a
 * propietary software including CDBASIC. The Candela system lost the battle of the swedish schools to
 * the Compis computer by TeleNova which was based on CP/M initially.  Later both lost to IBM PC as we know.
 * Candela Data continued to sell their system to the swedish industry without major successes despite great
 * innovation and spririt.
 *
 * Misc links about the boards supported by this driver.
 *-----------------------------------------------------
 * http://frakaday.blogspot.com/p/candela.html
 * http://elektronikforumet.com/forum/viewtopic.php?f=11&t=51424
 *
 *  TODO:
 *  Candela designs:   can09t, can09
 * -------------------------------------
 *  - Add PCB layouts   OK
 *  - Dump ROM:s,       OK      OK
 *  - Keyboard
 *  - Display/CRT
 *  - Clickable Artwork
 *  - Sound
 *  - Cassette i/f
 *  - Expansion bus
 *  - Expansion overlay
 *  - Interrupts
 *  - Serial            OK
 ****************************************************************************/

#include "emu.h"
#include "cpu/m6809/m6809.h"
#include "machine/6821pia.h"
#include "machine/6840ptm.h"
#include "machine/6850acia.h"
#include "machine/clock.h"
#include "machine/ram.h"
#include "machine/wd_fdc.h"
#include "video/mc6845.h"

// Features
#include "imagedev/cassette.h"
#include "bus/rs232/rs232.h"
#include "screen.h"

//**************************************************************************
//  MACROS / CONSTANTS
//**************************************************************************

//#define LOG_GENERAL (1U <<  0)
#define LOG_SETUP   (1U <<  1)
#define LOG_SCAN    (1U <<  2)
#define LOG_BANK    (1U <<  3)
#define LOG_SCREEN  (1U <<  4)
#define LOG_READ    (1U <<  5)
#define LOG_CS      (1U <<  6)
#define LOG_PLA     (1U <<  7)
#define LOG_PROM    (1U <<  8)

//#define VERBOSE (LOG_READ | LOG_GENERAL | LOG_SETUP | LOG_PLA | LOG_BANK)
//#define LOG_OUTPUT_FUNC printf
#include "logmacro.h"

#define LOGSETUP(...)   LOGMASKED(LOG_SETUP,   __VA_ARGS__)
#define LOGSCAN(...)    LOGMASKED(LOG_SCAN,    __VA_ARGS__)
#define LOGBANK(...)    LOGMASKED(LOG_BANK,    __VA_ARGS__)
#define LOGSCREEN(...)  LOGMASKED(LOG_SCREEN,  __VA_ARGS__)
#define LOGR(...)       LOGMASKED(LOG_READ,    __VA_ARGS__)
#define LOGCS(...)      LOGMASKED(LOG_CS,      __VA_ARGS__)
#define LOGPLA(...)     LOGMASKED(LOG_PLA,     __VA_ARGS__)
#define LOGPROM(...)    LOGMASKED(LOG_PROM,    __VA_ARGS__)

#ifdef _MSC_VER
#define FUNCNAME __func__
#else
#define FUNCNAME __PRETTY_FUNCTION__
#endif

#define PIA1_TAG "pia1"
#define PIA2_TAG "pia2"
#define PIA3_TAG "pia3"
#define PIA4_TAG "pia4"

/*
 *         The CAN09 v1.4 CPU board                                                  The CAN09 ROM and AD/DA board
 *       +-------------------------------------------------------------+  ___     +----------------------------------------------------------+
 *      +-+  +---+   +------+ +-----++-----+     +-----++-----+        |_|   |   +-+   +-----++-----++-----++-----++-----++-----+            |
 *      | |  |RST|   |      | | ROM ||     |+---+| RAM ||     | +--+   | |   |   | |J2 |PROM7||PROM6||PROM5||PROM4||PROM3||PROM2|  +---+     |
 *      | |  +---+   |      | |27256||62256||74 ||58256||62256| |CN|   | |   |   | |   |empty||empty||empty||empty||empty||empty|  |74 |     |
 *      | |      O   | 6809 | | MON ||empty||245||     ||empty| |J7|   | |   |   | |  o|     ||     ||     ||     ||     ||     |  |393|     |
 *      | |    J2O   |      | | 58B ||     ||   ||     ||     | |  |   | |   |   | |  o|     ||     ||     ||     ||     ||     |  |   |     |
 *      | |      O   |      | |     ||     ||   ||     ||     | |  |   | |   |   | |  o+-----++-----++-----++-----++-----++-----+  +---+     |
 *      | |      O   |      | +-----++-----++---++-----++-----+ +--+   | |EUR|   | |  o        ______                              +---+     |
 *      | |J1    O   |      |      +-------+         +-----+ +-----+   | |   |   | |  oJ1     | 74138|                             |74 |     |
 *      +-+      O   |      |      | 74138 |         |     | |     |   | |CN |   +-+  o       +------+                             |393|     |
 *      +-+      O +-+------+      +-------+  +-----+|     | |     |   | |J4 |  J4|8  o   +-----------------+  +-----------------+ |   |     |
 *      | |J6    O |74165 |        +--++-----+|     || PIA | | PIA |   | |   |    |8  o   | PIA 6821        |  | PIA 6821        | +---+     |
 *      | |      O +------+   +---+|CN||     || PTM || 6821| | 6821|   | |   |   +-+  o   |                 |  |                 |           |
 *      | |      O  VR1 VR2   |82S||J8||     || 6840||     | |     |   | |   |   | |  o   +-----------------+  +-----------------+           |
 *      | |      O +------+   |123||  ||ACIA ||     ||     | |     |   | |   |   | |  o   +-------++-------+   +--------+   +--------+       |
 *      +-+      O |7405  |   |   ||  || 6850||     ||     | |     |   | |   |   | |  o   |MPD1603|| 14051 |   | TL501  |   | 74LS02 |       |
 *      _===       +------+   ++--++--+|     ||     ||     | |     |   | |   |   | |      +-------++-------+   +--------+   +--------+       |
 * comp _|=        |74132 |    | 7400 |+----+++-----++-----+ +-----+   |_|   |   | |J3       +-------+       +---------+  +----------+       |
 * video ===       +------+    +------+     |MAX232 |                  | |___|   +-+         |MC34004|       |AD7528   |  |ADC0820   |       |
 *       +----------------------------------+-------+------------------+          +----------+-------+-------+---------+--+----------+-------+
 *
 */
/*
 * Candela CAN09 SBC
 * TODO:
 * - Map additional PIA:s on the ROM board
 * - Vram and screen
 * - Keyboard
 * - LCD
 * - AD/DA support for related BASIC functions
 * - Promett rom cartridge support
 */

#define SYSPIA_TAG PIA1_TAG
#define USRPIA_TAG PIA2_TAG

// Start offset for each device segment in bank array
#define RAM0 0x00
#define RAM1 0x08
#define PROM 0x10
#define RAM2 0x18
#define IO   0x1a

/* Candela CAN09 driver class */
  class can09t_state :  public driver_device
{
public:
	can09t_state(const machine_config &mconfig, device_type type, const char * tag)
		: driver_device(mconfig, type, tag)
		,m_maincpu(*this, "maincpu")
		,m_syspia(*this, SYSPIA_TAG)
		,m_usrpia(*this, USRPIA_TAG)
		,m_pia3(*this, PIA3_TAG)
		,m_pia4(*this, PIA4_TAG)
		,m_ptm(*this, "ptm")
		,m_acia(*this, "acia")
		,m_banksel(1)
	{ }
	required_device<cpu_device> m_maincpu;
	virtual void machine_start() override;
	DECLARE_READ8_MEMBER (read);
	DECLARE_WRITE8_MEMBER (write);
	DECLARE_READ8_MEMBER( syspia_A_r );
	DECLARE_READ8_MEMBER( syspia_B_r );
	DECLARE_WRITE8_MEMBER( syspia_B_w );
	DECLARE_WRITE_LINE_MEMBER( syspia_cb2_w);
	DECLARE_WRITE_LINE_MEMBER( usrpia_cb2_w);
	DECLARE_WRITE_LINE_MEMBER (write_acia_clock);
	void can09t(machine_config &config);
	void can09t_map(address_map &map);
protected:
	required_device<pia6821_device> m_syspia;
	required_device<pia6821_device> m_usrpia;
	required_device<pia6821_device> m_pia3;
	required_device<pia6821_device> m_pia4;
	required_device<ptm6840_device> m_ptm;
	required_device<acia6850_device> m_acia;

	uint8_t m_banksel;
	uint8_t *m_plap;
	uint8_t *m_epromp;

	uint8_t m_ram0[1024 *  8]; // IC3
	uint8_t m_ram1[1024 * 32]; // IC4
	uint8_t m_ram2[1024 *  8]; // IC5
private:
	enum {
		PLA_EPROM = 0x80,
		PLA_IO1   = 0x40,
		PLA_RAM2  = 0x20,
		PLA_RAM1  = 0x10,
		PLA_RAM0  = 0x08,
		PLA_RAM13 = 0x04,
		PLA_RAM14 = 0x02,
		PLA_MPX   = 0x01
	};

	enum {
		CPU_A4 = 0x010,
		CPU_A5 = 0x020,
		CPU_A6 = 0x040,
		CPU_A7 = 0x080,
		CPU_A8 = 0x100,
		CPU_A9 = 0x200,
	};

	enum { // 74138 outputs, naming after schematics
		X0XX = 0x0000,
		X1XX = 0x0010,
		X2XX = 0x0020,
		X3XX = 0x0030,
		X4XX = 0x0080,
		X5XX = 0x0090,
		X6XX = 0x00a0,
		X7XX = 0x00b0,
	};
};

void can09t_state::machine_start()
{
	LOG("%s()\n", FUNCNAME);

	/* TBP18S030 32 bytes fuse PROM controls the entire memory map in two parts/map-banks
	   BANK 0: 6f 6f 69 69 7b 7b ee ee e8 e8 ec bc ea ea 7f 7f
	   BANK 1: f1 f1 f5 f5 f3 f3 f7 f7 dc dc ec bc ea ea 7f 7f

	   Connected as follows:
	                  A12 -- A0  Y0 -- MPX* - latch for screen RAM
	                  A13 -- A1  Y1 -- RAM14
	                  A14 -- A2  Y2 -- RAM13
	                  A15 -- A3  Y3 -- RAM0
	   SYSPIA PB5 -- BANK -- A4  Y4 -- RAM1
	                 E+Q  -- S*  Y5 -- RAM2
	                             Y6 -- IO1
	                             Y7 -- EPROM

	   The PAL outputs are used as follows:
	   --------------------------------
	   Y0 IC12 MUX 74245: D0-D7 + MPX + RW => BD0-BD7
	   Y1 RAM14 is used together with the other outputs
	   Y2 RAM13 is used together with the other outputs
	   Y3 IC3 SRAM  6264: A0-A12 + RAM13:CS2 + RAM14:NC + RAM0:OE:CE + jumper B2 RW/pulled high:RW + VCC:BATTERY
	   Y4 IC4 SRAM 62256: A0-A12 + RAM13 + RAM14 + RW + RAM1:OE:CE + BD0-BD7
	   Y5 IC5 SRAM  6264: A0-A12 + RAM13:CS2 + RAM14:NC + RW + RAM2:OE:CE + BD0-BD7
	   Y6 IC11 DMX 74138: A4:A A5:B A7:C A8:G1 IO1:G2A A9:G2B => x0xx-x7xx see bellow:
	   Y7 IC2 PROM 27256: A0-A14 + EPROM

	   The 74138 demuxer outputs are used as follows:
	    A B C (A4 A5 and A7 respectivelly, not A6!)
	   ----------------------------------------------
	    0 0 0 Y0 x0xx ACIA   0xB100-B101
	    0 0 1 Y1 x1xx SYSPIA 0xB110-B113
	    0 1 0 Y2 x2xx USRPIA 0xB120-B123
	    0 1 1 Y3 x3xx PTM    0xB130-B137
	    1 0 0 Y4 x4xx        0xB180-B18F
	    1 0 1 Y5 x5xx J1, J2 0xB190-B19F
	    1 1 0 Y6 x6xx
	    1 1 1 Y7 x7xx J1, J2 0xB1B0-B1BF
	 */
	m_plap = (uint8_t*)(memregion ("plas")->base ());
	m_epromp = (uint8_t*)(memregion ("roms")->base ());
	memset(m_ram0, 0, sizeof(m_ram0));
	memset(m_ram1, 0, sizeof(m_ram1));
	memset(m_ram2, 0, sizeof(m_ram2));
};

READ8_MEMBER( can09t_state::read )
{
	LOG("%s %02x\n", FUNCNAME, offset);
	uint8_t pla_offset = 0;
	uint8_t pla_data = 0;
	uint8_t byte = 0;

	// Form the offset into the PLA (see above for explanation on PLA hookup)
	pla_offset = ((offset >> 12) & 0x0f) | (m_banksel ? 0x10 : 0x00);

	// Get the PLA data byte
	pla_data = m_plap[pla_offset & 0x1f];
	LOGPLA("PLA[%02x] read: %02x Bank%d\n", pla_offset, pla_data, m_banksel != 0 ? 0 : 1);

	// Find the device
	// IC2 EPROM - PAL Y7 PROM 27256: A0-A14 + EPROM
	if (~pla_data & PLA_EPROM)
	{
		byte = m_epromp[(offset & 0x7fff) % memregion("roms")->bytes()];
		LOGPROM("- EPROM %04x[%04x]->%02x\n", offset, (offset & 0x7fff) % memregion("roms")->bytes(), byte);
	}

	// IC3 RAM0 - PAL Y3 SRAM 6264: A0-A12 + RAM13:1 (RAM14 connected to NC)
	if ( (~pla_data & PLA_RAM0) && (pla_data & PLA_RAM13))
	{
		byte = m_ram0[offset % sizeof(m_ram0)];
		LOGPLA("- RAM0 %04x->%02x\n", offset, byte);
	}

	// IC4 RAM1 PAL Y4 SRAM 62256: A0-A12 + banked with RAM13/RAM14 data buffer 74LS245 enabled through PAL Y0
	if ( (~pla_data & PLA_RAM1) && (~pla_data & PLA_MPX) )
	{
		uint16_t ofs = (offset & 0x1fff) | ((pla_data & PLA_RAM13) ? 0x2000 : 0) | ((pla_data & PLA_RAM14) ? 0x4000 : 0);
		byte = m_ram1[ofs % sizeof(m_ram1)];
		LOGPLA("- RAM1 %04x->%02x\n", ofs, byte);
	}

	// IC5 RAM2 - PAL Y5 SRAM 6264: A0-A12 + RAM13:1 (RAM14 connected to NC) data buffer 74LS245 enabled through PAL Y0
	if ( (~pla_data & PLA_RAM0) && (pla_data & PLA_RAM13) && (~pla_data & PLA_MPX) )
	{
		byte = m_ram2[offset % sizeof(m_ram2)];
		LOGPLA("- RAM2 %04x->%02x\n", offset, byte);
	}

	// IC11 74138 Y6 demultiplexer : A5, A5, A7 + A8:1 + A9:0 maps in the i/o area at some
	if ( (~pla_data & PLA_IO1) && (~pla_data & PLA_MPX) && (offset & CPU_A8) && (~offset & CPU_A9) )
	{
		switch (offset & 0x00f0)
		{
		case X0XX: // ACIA
			LOGPLA("-- ACIA\n");
			byte = m_acia->read(space, offset & 1);
			break;
		case X1XX: // SYSPIA
			LOGPLA("-- SYSPIA\n");
			byte = m_syspia->read_alt(space, offset & 3);
			break;
		case X2XX: // USRPIA
			LOGPLA("-- USRPIA\n");
			byte = m_usrpia->read_alt(space, offset & 3);
			break;
		case X3XX: // PTM
			LOGPLA("-- PTM\n");
			byte = m_ptm->read(space, offset & 7);
			break;
		case X4XX: //
			LOGPLA("-- XX4X\n");
			break;
		case X5XX: // J1, J2
			LOGPLA("-- XX5X\n");
			break;
		case X6XX: //
			LOGPLA("-- XX6X\n");
			break;
		case X7XX: // J1, J2
			LOGPLA("-- XX7X\n");
			break;
		}
	}
	LOGR("- %04x <- %02x\n\n", offset, byte);
	return byte;
}

WRITE8_MEMBER( can09t_state::write )
{
	LOG("%s() %04x : %02x\n", FUNCNAME, offset, data);
	uint8_t pla_offset = 0;
	uint8_t pla_data = 0;

	// Form the offset into the PLA (see above for explanation on PLA hookup)
	pla_offset = ((offset >> 12) & 0x0f) | (m_banksel ? 0x10 : 0x00);

	// Get the PLA data byte
	pla_data = m_plap[pla_offset & 0x1f];
	LOGPLA("PLA[%02x] write: %02x Bank%d\n", pla_offset, pla_data, m_banksel != 0 ? 0 : 1);

	// Find the device
	// IC2 EPROM - PAL Y7 PROM 27256: A0-A14 + EPROM*
	if (~pla_data & PLA_EPROM)
	{
		LOGPLA("- EPROM (ignored) %04x<-%02x\n", offset, data);
	}

	// IC3 RAM0 - PAL Y3 SRAM 6264: A0-A12 + RAM13:1 (RAM14 connected to NC)
	if ( (~pla_data & PLA_RAM0) && (pla_data & PLA_RAM13))
	{
		m_ram0[offset % sizeof(m_ram0)] = data;
		LOGPLA("- RAM0 %04x<-%02x\n", offset, data);
	}

	// IC4 RAM1 Y4 SRAM 62256: A0-A12 + banked with RAM13/RAM14 data buffer 74LS245 enabled through PAL Y0
	if ( (~pla_data & PLA_RAM1) && (~pla_data & PLA_MPX) )
	{
		uint16_t ofs = (offset & 0x1fff) | ((pla_data & PLA_RAM13) ? 0x2000 : 0) | ((pla_data & PLA_RAM14) ? 0x4000 : 0);
		m_ram1[ofs % sizeof(m_ram1)] = data;
		LOGPLA("- RAM1 %04x<-%02x\n", ofs, data);
	}

	// IC5 RAM2 - PAL Y5 SRAM 6264: A0-A12 + RAM13:1 (RAM14 connected to NC) data buffer 74LS245 enabled through PAL Y0
	if ( (~pla_data & PLA_RAM0) && (pla_data & PLA_RAM13) && (~pla_data & PLA_MPX) )
	{
		m_ram2[offset % sizeof(m_ram2)] = data;
		LOGPLA("- RAM2 %04x->%02x\n", offset, data);
	}

	// IC11 74138 Y6 demultiplexer : A5, A5, A7 + A8:1 + A9:0 maps in the i/o area at some
	if ( (~pla_data & PLA_IO1) && (~pla_data & PLA_MPX) && (offset & CPU_A8) && (~offset & CPU_A9) )
	{
		LOGPLA("- IO1 %04x<-%02x\n", offset, data);
		switch (offset & 0x00f0)
		{
		case X0XX: // ACIA
			LOGPLA("-- ACIA\n");
			m_acia->write(space, offset & 1, data);
			break;
		case X1XX: // SYSPIA
			LOGPLA("-- SYSPIA\n");
			m_syspia->write_alt(space, offset & 3, data);
			break;
		case X2XX: // USRPIA
			LOGPLA("-- USRPIA\n");
			m_usrpia->write_alt(space, offset & 3, data);
			break;
		case X3XX: // PTM
			LOGPLA("-- PTM\n");
			m_ptm->write(space, offset & 7, data);
			break;
		case X4XX: //
			LOGPLA("-- XX4X\n");
			break;
		case X5XX: // J1, J2
			LOGPLA("-- XX5X\n");
			break;
		case X6XX: //
			LOGPLA("-- XX6X\n");
			break;
		case X7XX: // J1, J2
			LOGPLA("-- XX7X\n");
			break;
		}
	}
}

READ8_MEMBER( can09t_state::syspia_A_r )
{
	LOG("%s()\n", FUNCNAME);
	return 0;
}

READ8_MEMBER( can09t_state::syspia_B_r )
{
	LOG("%s()\n", FUNCNAME);
	return 0;
}

WRITE8_MEMBER( can09t_state::syspia_B_w )
{
	LOG("%s(%02x)\n", FUNCNAME, data);

	m_banksel = (data & 0x20) ? 0x10 : 0;
	LOGBANK("Bank select: %d", (m_banksel >> 4) & 1);
}

WRITE_LINE_MEMBER(can09t_state::syspia_cb2_w)
{
	LOG("%s(%02x)\n", FUNCNAME, state);
}

WRITE_LINE_MEMBER(can09t_state::usrpia_cb2_w)
{
	LOG("%s(%02x)\n", FUNCNAME, state);
}

WRITE_LINE_MEMBER (can09t_state::write_acia_clock){
		m_acia->write_txc (state);
		m_acia->write_rxc (state);
}

/*
 * Address map from documentation based on specific PAL
 *
 *   BANK 0                            BANK 1
 *   0x0000-0x34ff PROM VDU-program    0x0000-0x34ff RAM0 user applications (0)
 *   0x3500-0x5fff PROM simulator      0x3500-0x5fff RAM0 user applications (0)
 *   0x6000-0x7fff RAM screen memory   0x6000-0x7fff RAM0 user applications (0)
 *   0x8000-0x9fff RAM screen memory   0x8000-0x9fff PROM user applications (2)
 *  *0xa000-0xafff RAM Stack, system   0xa000-0xafff RAM Stack, system
 *  *0xb000-0xb0ff Free                0xb000-0xb0ff Free
 *  *0xb100-0xb101 ACIA                0xb100-0xb101 ACIA
 *  *0xb110-0xb113 PIA System          0xb110-0xb113 PIA System
 *  *0xb120-0xb123 PIA User apps       0xb120-0xb123 PIA User apps
 *  *0xb130-0xb137 PTM                 0xb130-0xb137 PTM
 *  *0xb180-0xb1bf Free                0xb180-0xb1bf Free
 *  *0xb200-0xb3ff Free                0xb200-0xb3ff Free
 *  *0xc000-0xdfff RAM User apps (1)   0xc000-0xdfff RAM User apps (1)
 *  *0xe000-0xffff PROM monitor        0xe000-0xffff PROM monitor
 */

void can09t_state::can09t_map(address_map &map)
{
// Everything is dynamically and asymetrically mapped through the PAL decoded by read/write
	map(0x0000, 0xffff).rw(this, FUNC(can09t_state::read), FUNC(can09t_state::write));
}

static INPUT_PORTS_START( can09t )
INPUT_PORTS_END

/*
 * Candela Main Unit
 * TODO:
 * - Map PIA:S
 * - ROM/RAM paging by using the PIA:s and the myriad of 74138:s on the board
 * - Vram and screen for the 6845 CRTC
 * - Keyboard
 * - Serial port
 * - Floppy controller
 * - Split out commonalities in a candela_state base class for can09 and can09t
 */
/* Candela main unit driver class */
  class can09_state :  public driver_device
{
public:
	can09_state(const machine_config &mconfig, device_type type, const char * tag)
		: driver_device(mconfig, type, tag)
		,m_maincpu(*this, "maincpu")
		,m_pia1(*this, PIA1_TAG)
		,m_ram(*this, RAM_TAG)
		,m_bank1(*this, "bank1")
		,m_crtc(*this, "crtc")
	{ }
	required_device<cpu_device> m_maincpu;
	virtual void machine_reset() override;
	virtual void machine_start() override;
	DECLARE_READ8_MEMBER( pia1_A_r );
	DECLARE_WRITE8_MEMBER( pia1_A_w );
	DECLARE_READ8_MEMBER( pia1_B_r );
	DECLARE_WRITE8_MEMBER( pia1_B_w );
	DECLARE_WRITE_LINE_MEMBER( pia1_cb2_w);
	uint32_t screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
	void can09(machine_config &config);
	void can09_map(address_map &map);
protected:
	required_device<pia6821_device> m_pia1;
	required_device<ram_device> m_ram;
	required_memory_bank m_bank1;
	required_device<h46505_device> m_crtc;
};

void can09_state::machine_reset()
{
	LOG("%s()\n", FUNCNAME);
	m_bank1->set_entry(0);
}

void can09_state::machine_start()
{
	LOG("%s()\n", FUNCNAME);
	m_bank1->configure_entries(0, 8, m_ram->pointer(), 0x8000);
}

uint32_t can09_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
{
	int x, y;
#if 0
	int vramad;
	UINT8 *chardata;
	UINT8 charcode;
#endif

	LOGSCREEN("%s()\n", FUNCNAME);
	//  vramad = 0;
	for (int row = 0; row < 72 * 8; row += 8)
	{
		for (int col = 0; col < 64 * 8; col += 8)
		{
#if 0
			/* look up the character data */
			charcode = m_vram[vramad];
			if (VERBOSE && charcode != 0x20 && charcode != 0) LOGSCREEN("\n %c at X=%d Y=%d: ", charcode, col, row);
			chardata = &m_char_ptr[(charcode * 8)];
#endif
			/* plot the character */
			for (y = 0; y < 8; y++)
			{
				//              if (VERBOSE && charcode != 0x20 && charcode != 0) LOGSCREEN("\n  %02x: ", *chardata);
				for (x = 0; x < 8; x++)
				{
					//                  if (VERBOSE && charcode != 0x20 && charcode != 0) LOGSCREEN(" %02x: ", *chardata);
					bitmap.pix16(row + y, col + x) = x & 1; //(*chardata & (1 << x)) ? 1 : 0;
				}
				//              chardata++;
			}
			//          vramad++;
		}
		//      if (VERBOSE && charcode != 0x20 && charcode != 0) LOGSCREEN("\n");
	}

	return 0;
}

READ8_MEMBER( can09_state::pia1_A_r )
{
	LOG("%s()\n", FUNCNAME);
	return 0x40;
}

WRITE8_MEMBER( can09_state::pia1_A_w )
{
	LOG("%s(%02x)\n", FUNCNAME, data);
}

READ8_MEMBER( can09_state::pia1_B_r )
{
	LOG("%s()\n", FUNCNAME);
	return 0;
}

WRITE8_MEMBER( can09_state::pia1_B_w )
{
	//  UINT8 *RAM = memregion("maincpu")->base();
	LOG("%s(%02x)\n", FUNCNAME, data);
	//  membank("bank1")->set_entry((data & 0x70) >> 4);
	m_bank1->set_entry((data & 0x70) >> 4);
#if 0
	switch (data & 0x70){
	case 0x00: membank("bank1")->set_base(&RAM[0x10000]); break;
	case 0x10: membank("bank1")->set_base(&RAM[0x18000]); break;
	case 0x20: membank("bank1")->set_base(&RAM[0x20000]); break;
	case 0x30: membank("bank1")->set_base(&RAM[0x28000]); break;
	case 0x40: membank("bank1")->set_base(&RAM[0x30000]); break;
	case 0x50: membank("bank1")->set_base(&RAM[0x38000]); break;
	case 0x60: membank("bank1")->set_base(&RAM[0x40000]); logerror("strange memory bank"); break;
	case 0x70: membank("bank1")->set_base(&RAM[0x48000]); logerror("strange memory bank"); break;
	default: logerror("%s Programming error, please report!\n", FUNCNAME);
	}
#endif
}

WRITE_LINE_MEMBER(can09_state::pia1_cb2_w)
{
	LOG("%s(%02x)\n", FUNCNAME, state);
}

static INPUT_PORTS_START( can09 )
	PORT_START("LINE0")
	PORT_START("LINE1")
	PORT_START("LINE2")
	PORT_START("LINE3")
	PORT_START("LINE4")
INPUT_PORTS_END

// traced and guessed from pcb images and debugger
// It is very likelly that this is a PIA based dynamic address map, needs more analysis
void can09_state::can09_map(address_map &map)
{
/*
 * Port A=0x18 B=0x20 erase 0-7fff
 * Port A=0x18 B=0x30 erase 0-7fff
 * Port A=0x18 B=0x00
 * Port A=0x10 B=
*/
//  AM_RANGE(0x0000, 0x7fff) AM_RAM
	map(0x0000, 0x7fff).ram().bankrw("bank1");
	map(0xe000, 0xffff).rom().region("roms", 0);
	map(0xe020, 0xe020).w(m_crtc, FUNC(h46505_device::address_w));
	map(0xe021, 0xe021).w(m_crtc, FUNC(h46505_device::register_w));
	map(0xe034, 0xe037).rw(m_pia1, FUNC(pia6821_device::read), FUNC(pia6821_device::write));

#if 0
	map(0xb100, 0xb101).rw("acia", FUNC(acia6850_device::read), FUNC(acia6850_device::write));
	map(0xb110, 0xb113).rw(m_pia1, FUNC(pia6821_device::read_alt), FUNC(pia6821_device::write_alt));
	map(0xb120, 0xb123).rw(PIA2_TAG, FUNC(pia6821_device::read_alt), FUNC(pia6821_device::write_alt));
	map(0xb130, 0xb137).rw("ptm", FUNC(ptm6840_device::read), FUNC(ptm6840_device::write));
	map(0xb200, 0xc1ff).rom().region("roms", 0x3200);
	map(0xc200, 0xdfff).ram(); /* Needed for BASIC etc */
#endif
}

#ifdef UNUSED_VARIABLE
static DEVICE_INPUT_DEFAULTS_START( terminal )
	DEVICE_INPUT_DEFAULTS( "RS232_TXBAUD", 0xff, RS232_BAUD_300 )
	DEVICE_INPUT_DEFAULTS( "RS232_RXBAUD", 0xff, RS232_BAUD_300 )
	DEVICE_INPUT_DEFAULTS( "RS232_STARTBITS", 0xff, RS232_STARTBITS_1 )
	DEVICE_INPUT_DEFAULTS( "RS232_DATABITS", 0xff, RS232_DATABITS_7 )
	DEVICE_INPUT_DEFAULTS( "RS232_PARITY", 0xff, RS232_PARITY_NONE )
	DEVICE_INPUT_DEFAULTS( "RS232_STOPBITS", 0xff, RS232_STOPBITS_2 )
DEVICE_INPUT_DEFAULTS_END
#endif

/* Fake clock values until we TODO: figure out how the PTM generates the clocks */
#define CAN09T_BAUDGEN_CLOCK XTAL(1'843'200)
#define CAN09T_ACIA_CLOCK (CAN09T_BAUDGEN_CLOCK / 12)

MACHINE_CONFIG_START(can09t_state::can09t)
	MCFG_DEVICE_ADD("maincpu", MC6809, XTAL(4'915'200)) // IPL crystal
	MCFG_DEVICE_PROGRAM_MAP(can09t_map)

	/* --PIA inits----------------------- */
	MCFG_DEVICE_ADD(SYSPIA_TAG, PIA6821, 0) // CPU board
	MCFG_PIA_READPA_HANDLER(READ8(*this, can09t_state, syspia_A_r))
	MCFG_PIA_READPB_HANDLER(READ8(*this, can09t_state, syspia_B_r))
	MCFG_PIA_WRITEPB_HANDLER(WRITE8(*this, can09t_state, syspia_B_w))
	MCFG_PIA_CB2_HANDLER(WRITELINE(*this, can09t_state, syspia_cb2_w))
	/* 0xE1FB 0xB112 (SYSPIA Control A) = 0x00 - Channel A IRQ disabled */
	/* 0xE1FB 0xB113 (SYSPIA Control B) = 0x00 - Channel B IRQ disabled */
	/* 0xE203 0xB110 (SYSPIA DDR A)     = 0x00 - Port A all inputs */
	/* 0xE203 0xB111 (SYSPIA DDR B)     = 0x7F - Port B mixed mode */
	/* 0xE20A 0xB112 (SYSPIA Control A) = 0x05 - IRQ A enabled on falling transition on CA2 */
	/* 0xE20A 0xB113 (SYSPIA Control B) = 0x34 - CB2 is low and lock DDRB */
	/* 0xE20E 0xB111 (SYSPIA port B)    = 0x10 - Data to port B */
	MCFG_DEVICE_ADD(USRPIA_TAG, PIA6821, 0) // CPU board
	MCFG_PIA_CB2_HANDLER(WRITELINE(*this, can09t_state, usrpia_cb2_w))
	/* 0xE212 0xB122 (USRPIA Control A) = 0x00 - Channel A IRQ disabled */
	/* 0xE212 0xB123 (USRPIA Control B) = 0x00 - Channel B IRQ disabled */
	/* 0xE215 0xB120 (USRPIA DDR A)     = 0x00 - Port A all inputs */
	/* 0xE215 0xB121 (USRPIA DDR B)     = 0xFF - Port B all outputs */
	/* 0xE21A 0xB122 (USRPIA Control A) = 0x34 - CA2 is low and lock DDRB */
	/* 0xE21A 0xB123 (USRPIA Control B) = 0x34 - CB2 is low and lock DDRB */
	MCFG_DEVICE_ADD(PIA3_TAG, PIA6821, 0) // ROM board
	MCFG_DEVICE_ADD(PIA4_TAG, PIA6821, 0) // ROM board

	MCFG_DEVICE_ADD("ptm", PTM6840, 0)

	/* RS232 usage: mame can09t -window -debug -rs232 terminal */
	MCFG_DEVICE_ADD("acia", ACIA6850, 0)
	MCFG_ACIA6850_TXD_HANDLER(WRITELINE ("rs232", rs232_port_device, write_txd))
	MCFG_ACIA6850_RTS_HANDLER(WRITELINE ("rs232", rs232_port_device, write_rts))
	MCFG_DEVICE_ADD("rs232", RS232_PORT, default_rs232_devices, "terminal")
	MCFG_RS232_RXD_HANDLER(WRITELINE ("acia", acia6850_device, write_rxd))
	MCFG_RS232_CTS_HANDLER(WRITELINE ("acia", acia6850_device, write_cts))

	MCFG_DEVICE_ADD ("acia_clock", CLOCK, CAN09T_ACIA_CLOCK)
	MCFG_CLOCK_SIGNAL_HANDLER(WRITELINE (*this, can09t_state, write_acia_clock))
MACHINE_CONFIG_END

#define CAN09_X1_CLOCK XTAL(22'118'400)        /* UKI 22118.40 Khz */
#define CAN09_CPU_CLOCK (CAN09_X1_CLOCK / 16) /* ~1.38MHz Divider needs to be check but is the most likelly */
MACHINE_CONFIG_START(can09_state::can09)
	MCFG_DEVICE_ADD("maincpu", MC6809E, CAN09_CPU_CLOCK) // MC68A09EP
	MCFG_DEVICE_PROGRAM_MAP(can09_map)

	/* RAM banks */
	MCFG_RAM_ADD(RAM_TAG)
	MCFG_RAM_DEFAULT_SIZE("768K")

	// CRTC  init
	MCFG_MC6845_ADD("crtc", H46505, "screen", CAN09_CPU_CLOCK) // TODO: Check actual clock source, An 8MHz UKI crystal is also nearby
	MCFG_MC6845_SHOW_BORDER_AREA(false)
	MCFG_MC6845_CHAR_WIDTH(8)
	//MCFG_MC6845_UPDATE_ROW_CB(can09_state, crtc_update_row) // not written yet

	/* Setup loop from data table in ROM: 0xFFCB 0xE020 (CRTC register number), 0xFFD0 0xE021 (CRTC register value)
	    Reg  Value Comment
	    0x00 0x55  Horizontal Total number of characters,
	    0x01 0x40  Horizontal Displayed number of characters
	    0x02 0x43  Horizontal Sync Position, character number
	    0x03 0x03  Horizontal Sync width, number of charcters
	    0x04 0x50  Vertical Total number of characters
	    0x05 0x09  Vertical Total Adjust number of characters
	    0x06 0x48  Vertical Displayed number of characters
	    0x07 0x4B  Vertical Sync Position, character number
	    0x08 0x00  Interlace Mode/Scew, Non-Interlaced
	    0x09 0x03  Max Scan Line Address Register
	    0x0A 0x00  Cursor Start
	    0x0B 0x0A  Cursor End
	    0x0C 0x00  Start Address hi
	    0x0D 0x00  Start Address lo
	    0x0E 0x00  Cursor hi
	    0x0F 0x00  Cursor lo
	    Note - no init of Light Pen registers
	*/



	/* screen - totally faked value for now */
	MCFG_SCREEN_ADD("screen", RASTER)
	MCFG_SCREEN_REFRESH_RATE(50)
	MCFG_SCREEN_RAW_PARAMS(XTAL(4'000'000)/2, 512, 0, 512, 576, 0, 576)
	MCFG_SCREEN_UPDATE_DRIVER(can09_state, screen_update)
	MCFG_SCREEN_PALETTE("palette")
	MCFG_PALETTE_ADD_MONOCHROME("palette")

	/* Floppy */
	MCFG_WD1770_ADD("wd1770", XTAL(8'000'000) ) // TODO: Verify 8MHz UKI crystal assumed to be used
#if 0
	MCFG_FLOPPY_DRIVE_ADD("wd1770:0", candela_floppies, "3dd", floppy_image_device::default_floppy_formats)
	MCFG_SOFTWARE_LIST_ADD("flop3_list", "candela")
#endif

	/* --PIA inits----------------------- */
	MCFG_DEVICE_ADD(PIA1_TAG, PIA6821, 0) // CPU board
	MCFG_PIA_READPA_HANDLER(READ8(*this, can09_state, pia1_A_r))
	MCFG_PIA_WRITEPA_HANDLER(WRITE8(*this, can09_state, pia1_A_w))
	MCFG_PIA_READPB_HANDLER(READ8(*this, can09_state, pia1_B_r))
	MCFG_PIA_WRITEPB_HANDLER(WRITE8(*this, can09_state, pia1_B_w))
	MCFG_PIA_CB2_HANDLER(WRITELINE(*this, can09_state, pia1_cb2_w))
	/* 0xFF7D 0xE035 (PIA1 Control A) = 0x00 - Channel A IRQ disabled */
	/* 0xFF81 0xE037 (PIA1 Control B) = 0x00 - Channel A IRQ disabled */
	/* 0xFF85 0xE034 (PIA1 DDR A)     = 0x1F - Port A mixed mode */
	/* 0xFF89 0xE036 (PIA1 DDR B)     = 0x79 - Port B mixed mode */
	/* 0xFF8D 0xE035 (PIA1 Control A) = 0x04 - Channel A lock DDR */
	/* 0xFF8F 0xE037 (PIA1 Control B) = 0x04 - Channel B lock DDR */
	/* 0xFF93 0xE034 (PIA1 Port B)    = 0x18 - Write Data on Port B */

#if 1
	MCFG_DEVICE_ADD(PIA2_TAG, PIA6821, 0) // CPU board
	MCFG_DEVICE_ADD("acia1", ACIA6850, 0) // CPU board
	MCFG_DEVICE_ADD("acia2", ACIA6850, 0) // CPU board
#endif
MACHINE_CONFIG_END

ROM_START( can09t ) /* The smaller grey computer */
	ROM_REGION(0x10000, "roms", 0)
	/* CAN09 v7 and CDBASIC 3.8 */
	ROM_LOAD( "ic2-mon58b-c8d7.bin", 0x0000, 0x8000, CRC(7eabfec6) SHA1(e08e2349035389b441227df903aa54f4c1e4a337) )

	ROM_REGION(0x1000, "plas", 0)
	/* Programmable logic for the CAN09 1.4 PCB (CAN21.1) */
	ROM_LOAD( "ic10-21.1.bin",       0x0000, 0x20,   CRC(b75ac72d) SHA1(689363200035b11a823d17a8d717f313eeefc3bf) )
ROM_END

ROM_START( can09 ) /* The bigger black computer CAN v1 */
	ROM_REGION(0x10000, "roms", 0)
	ROM_LOAD( "ic14-vdu42.bin", 0x0000, 0x2000, CRC(67fc3c8c) SHA1(1474d6259646798377ef4ce7e43d3c8d73858344) )
ROM_END

//    YEAR  NAME    PARENT  COMPAT  MACHINE  INPUT   CLASS         INIT        COMPANY            FULLNAME            FLAGS
COMP( 1984, can09,  0,      0,      can09,   can09,  can09_state,  empty_init, "Candela Data AB", "Candela CAN09 v1", MACHINE_NOT_WORKING | MACHINE_NO_SOUND_HW | MACHINE_IMPERFECT_GRAPHICS)
COMP( 1984, can09t, 0,      0,      can09t,  can09t, can09t_state, empty_init, "Candela Data AB", "Candela CAN09",    MACHINE_NO_SOUND_HW )