[WIP] Simon Merrett's Arduboy Clone

Oh, here’s the screen just placed (not soldered until I get the bootloader working and buttons recognised).


Here’s a footprint mistake I made for the mounting pins - can’t insert flush as a result! Shifting the main row by 1.27mm should fix that, and I also need to rotate the slots for the backlight terminals 90 degrees:

5 Likes

Here’s a simple test to check all the buttons work. I found that the 32kHz crystals and caps are relatively expensive and, despite having ordered a few to build this board with, I thought I’d chance a crystalless bootloader.

I opted for the adafruit itsybitsy M0 and this works nicely. I uploaded using the adafruit instructions for uf2 bootloader, along with Atmel Studio 7 and an Atmel ICE. The ICE header on this board was well worth it for the ease of burning the bootloader!

Despite my comment earlier that these buttons are rubbish, they are quite sensitive. The real problem with them is the lack of feedback - you can’t even sense the deflection, let alone a click.

You may notice that the power LED isn’t working. I’ve tried it in both orientations, so I don’t know what’s going on there - but who cares if you can get your RGB LED dancing to the tune of your buttons!

The joystick is a bit disappointing. I need to check if I have soldered it in the wrong way round - the connections are certainly wrong - up is down and down is up. That’s my problem, not the joystick’s - the problem I think the joystick may have is that it seems that you need to be depressing the centre button to register the direction pushes. Difficult to explain but there’s a small chance the likely-wrong orientation is to blame for this.

Attempting the screen next week. I need to plan a few devices for Arduboy SW ninjas to help with a SAMD21 port of the relevant libraries. Any takers, in principle? Preferably UK based, just to keep the shipping costs reasonable. BTW, if you know that I’m wasting my time because a SAMD21 port is done, please shout and link to where it is!

1 Like

Someone stole your screen!

Hah! That’s the most expensive part of the BOM and isn’t getting soldered until the critical cheap parts are verified functional. Next week hopefully.

1 Like

Might not be helpful, but Adafruit has a port for their SAMD51 handhelds, to be used in conjunction with their ‘Arcada’ library:



2 Likes

Well that does sound helpful, thanks. I’d definitely like advice from the SW ninjas on whether it’s better to adapt the arcada library to support the samd21 and the large lcd or whether it’s better to do something else. The key differences I think might cause issues with adapting the arcada lib are:

  • the buttons are either analogue or via a shift register.
  • The adafruit boards all have adafruit screen libraries written
  • samd51 vs samd21.

I could change the buttons (but prefer not to need a shift register in the BoM) and upgrade to the samd51 fairly easily but I would imagine the more people will have a samd21 based board at home / for cheap, for anyone who wants to diy this before making their own.

@Pharap, @MLXXXp and others, what do you think is the best way forward?

1 Like

Asking for me by name is of course an excellent way to curry favour. :P
(Fun fact: originally the idiom was ‘curry Fauvel’. Fauvel was a horse.)

The SAMD21’s spec is just slightly off the LPC11U68 (also a Cortex M0+) used in the Pokitto.

The main difference being the '21 has 32KB of RAM and the 'U68 has 36KB of RAM.

Unfortunately that doesn’t mean you could just reuse the Pokitto version of the Arduboy2 library because it’s based on the PokittoLib, which is in turn using mbed’s libraries which possibly wouldn’t work with the '21 and you’d need a particular environment to use them anyway.

What it does mean though is that an Arduboy2 port is completely realistic.

The '51 is a much more complex piece of hardware.
It’s got an FPU, twice the progmem, 6 times the RAM, a crypto engine and loads of other features.

Honestly I think @uXe’s suggestion of reusing Adafruit’s version is probably somewhat viable.
At the very least it’s a good starting point for replacing the assembly portions of the Arduboy2 library with some equivalent C++ code.

The remaining issues would be differences in pinouts and whether the '21 is fast enough to not need to drop to assembly.
It should be if you’re sticking with a black and white screen.
If you’re moving up to a colour TFT then it’s going to be more of a challenge.

I’ll admit it’s tempting (not least because I’m close enough to stop over, filch all your cream teas and be back before sundown if I didn’t hang about), but I probably shouldn’t add more things to my backlog.

I could probably help out later down the line,
but I’m of little use for the hardware side of things anyway.
When the hardware’s been decided on I might be of more use.

I’m going to be completely shameless and point out this commit. :P

The code was indeed borrowed from the Pokitto Arduboy2 port (or at least the older version of it).

Definitely - that’s really starting to stand out as a defining feature of an Arduboy-derivative. This project will stick with monochrome. If this LCD doesn’t work out, I’ll look at other monochrome options, so we can focus libraries only on BW.

Excellent. This is enough for me to stick with the SAMD21G18A

Yes, I’m not far off nailing that down. In fact, having looked a little at the Arduboy2 repo this morning (for the first time - can you tell I’m more into the HW than SW? :laughing: ) I don’t think keeping the buttons as digital inputs is an issue now.

@Pharap (now I know how to summon you!) what info would you want from the HW spec to make porting easier? I presume a schematic is ideal for EEs but the embedded dev would probably prefer some pinout / port tables rather than having to search a schematic matching up net labels.

1 Like

Speaking purely for myself, though I presume others might agree…

  • The CPU pinouts, including whether they’re digital, analogue, PWM capable and what they’re actually connected to. Specifically with descriptive names - don’t use strange symbols like ∅ or abbreviations like RDY specify ‘clock’ or ‘ready’.
    • Doesn’t need to be all the pinouts per se, but at least all the important ones and one or two unconnected pins - for seeding the PRNG.
  • The datasheet for the screen specifying which commands it accepts (assuming it’s one of those screens that has a chip controlling it that takes commands over I2C or SPI). I doubt you’ll find them listed outside the datasheet anywhere unfortunately.
  • Info about the sound hardware (though I’m still pretty useless at sound so it probably won’t be me handling that one).

Essentially whatever’s needed to know how to interface and control the hardware.

You presume right. I can’t even read half the board schematics I see.

Datasheets I can just about manage to skim relevant information from,
but it usually takes quite a bit of searching to separate the wheat from the chaff.

1 Like


@Pharap, any good? I realise I haven’t given each pin the full PWM/ADC labelling but are there any other than the ones I have annotated that you would need to know this for? What about interrupt numbers for the button pins? I can’t remember from my quick glance but is the Arduboy2 library polling buttons?
I have put TBC by all the Arduino Variant pin numbers because these are easily definable, so they could match either the existing Arduboy scheme or something different, for example depending on whether Speaker 1 (normal digital output) or Speaker 2 (SAMD21 DAC) was what we wanted to use for the audio out pin.UC1701.pdf (540.9 KB) the UC1701x LCD controller datasheet is also attached. Does it contain the instructions needed?

1 Like

Looks pretty useful.

I’m assuming ‘crystal’ is some kind of piezoelectric quartz clock signal?
No clue what ‘Xtal’ is, or what ‘floating’ logic means.

I was half hoping input/output/bidirectional and digital/analogue would be distinct columns, but it’s still usable.

Ultimately, I think PWM is only used for the LED and possibly the speaker (on the Arduboy),
so as long as there are designated pins that are suitable for that then that’s all that should be needed in terms of PWM.

It’s a good thing you made this list, I probably would have forgotten about SPI and USB pins because they’re usually hidden behind some kind of Arduino class.

Are the SWD pins “software wire debug”? If not, I have no clue what they’re for.

There’s still a handful of pins I can’t guess the purpose of from the name:

  • IR_Tx, IR_Rx
    • Though I’m guessing they might be the TX and RX LEDs or something to do with serial uploading
  • LCD_CS, LCD_CD and LCD_RST
    • Are these something to do with the screen? If so, is the screen not connected over SPI? Or are there two SPI interfaces?

At any rate the most important stuff is there.

I think the first port of call should be hooking up the buttons and any LEDs in order to write some simple “light up the LED when the button is pressed” programs, which will prove that the buttons and LEDs are all in working order.

After that the screen is the elephant in the room and will probably take the most work.
(I’ll get to that in a bit.)

Then when the screen is running fine the next issue will be sound and the speakers.

Once sound is working that’s probably everything sorted in terms of hardware, and the only remaining issue (which may or may not be an issue depending on how things go) would be optimisation.
Chances are there probably won’t be much optimisation to do (if any) because the CPU is sufficiently more powerful.
If anything, there will probably be a bit of optimising for power consumption so the console can run for longer without charging.

I believe it uses interrupts for sound and maybe timers,
but not for the screen or buttons (it polls the pins once per frame),
and not for anything else as far as I’m aware.

It has a simplified overview table on page 12 and a full ‘command description’ on page 13 describing the instructions.

It looks like is has almost all of the same commands the SSD1306 has, which is handy.

Page 33 has the power-up sequence and sleep mode sequence info, which is also handy.
There’s also some more examples on page 35.

The screen seems to have 64 rows much like the 1306.

The only thing I can’t find is something that specifies how the frame data should be laid out.
If it’s in the same format as the SSD1306 then getting it up and running will be incredibly easy.
If it’s not then things will be more difficult and writing to the screen will consume more processing power, but it would probably still be doable.


The only piece of information that wasn’t on the table was timer information.
Specifically how many timers the SAMD has and what their characteristics are.
The Arduboy doesn’t use many timers, but it does have a timer for keeping track of frame durations in order to cap the framerate, and obviously there’s a timer for controlling sound output to.

If SAMD works fine with the Arduino libraries then the former is less of an issue because millis should work properly.
The latter on the other hand is probably something that the library will have to handle itself, but I’m not entirely certain - sound programming is not my forte at all.

(Fun fact: the word forte comes from the French word ‘fort’ which doesn’t actually have the stereotypical -e sound - the -e was added either for effect or in ignorance, which means the word ‘forte’ is actually a hyperforeignism.)


P.S. I’m somewhat disappointed by your spelling of analogue. :P

Well, addressing your reply in priority order (!) you will at least be consoled to hear that I did think twice before adopting American English spelling. My reasoning was that it was consistent with the code spelling.

Thanks for the rest of the response - I’ll have a crack at finding out the screen stuff now.

The buttons are all working (except for my joystick which is connected to the D pad buttons and I think it is in reverse orientation) - hopefully you can see this demo of the buttons and RGB LED.

Great. As far as timers go, SAMD21 has them and millis() should work fine. As for timer interrupts, they may need setting up from scratch (happy to work out how to do that).

They’re for the external crystal that the SAMD21-based Arduino Zero runs its main clock from. I have used an Adafruit bootloader that generates its clock signal internally to the uC, so we are just reserving these pins for now - not connecting anything to them.

Floating pins mean they’re not connected to anything - that’s what I thought you could use to seed the PRNG, as their analogue value could fluctuate from GND-VCC.

I’ll update.

Yes. I made a mistake and called them Single Wire Debug. It appears you may have too - Serial Wire Debug is the name, apparently. I put their purpose in the right hand column - they are purely to load the bootloader and any port of the Arduboy2 library should have nothing to do with them. I included them for completeness.

Close. I intended to allow this device to have the hardware that would enable wireless multiplayer. I think infrared 36kHz or 38kHz LEDs and receivers could be a cool way to do that. I don’t know how the SW developers would come up with a common way of doing that, but I thought it would be cool so I added space on the PCB and connected up the pins for the components (LED, transistor, resistors, infrared receiver).

Ref the LCD controller, here’s an extract from the old u8glib library by Oli Kraus, which I used with an Arduino Pro Mini clone to get a bitmap onto the screen. I have highlighted the two modes that we’d probably be interested in (hardware SPI):


And here’s the equivalent entry for the SSD1306, which I have highlighted the mode I presume the Arduboy’s interface is closest to.

And here’s what the pin codes denote:image
so “LCD_CD” equates to “a0” in the constructor and “LCD_RST” equates to the screen’s reset pin.
Will keep working on the frame data layout.

@Pharap does this comparison of the SSD1306 (on the right) and UC1701x source in u8glib help work out the difference in frame data layout?

Also, there’s this demo code from the manufacturer of the LCD. Is it helpful?

//----------------------------------------------------------------------
	/*EASTRISING TECHNOLOGY CO,.LTD.*/
	// Module    : ERC12864-655 Series
	// Lanuage   : C51 Code
	// Create    : JAVEN
	// Date      : 2010-10-05
	// Drive IC  : UC1701
	// INTERFACE : 8080_8bit
	// MCU 		 : AT89LV52
	// VDD		 : 3.3V   VLCD: 9.2V    4 times boosting
	//----------------------------------------------------------------------

#include <AT89X52.H>
#include <intrins.h>

#define uint unsigned int
#define uchar unsigned char
#define TIMING                 8080			
#define RS                     P3_3
#define RW_WR                  P3_1
#define E_RD                   P3_0
#define DATA_BUS               P1
#define CS1                    P3_5
#define RST                    P3_4
sbit	int0=P3^2;
sbit key_add=P0^1;
sbit key_dec=P0^2;
uchar Contrast_level=21;
bit log=0;

#define DISPLAY_ON()           Write_Instruction(0xaf)   //  Display on
#define DISPLAY_OFF()          Write_Instruction(0xae)   //  Display off
#define SET_ADC()              Write_Instruction(0xa1)   //  Reverse disrect (SEG131-SEG0)
#define CLEAR_ADC()            Write_Instruction(0xa0)   //  Normal disrect (SEG0-SEG131)
#define REVERSE_DISPLAY_ON()   Write_Instruction(0xa7)   //  Reverse display : 0 illuminated
#define REVERSE_DISPLAY_OFF()  Write_Instruction(0xa6)   //  Normal display : 1 illuminated
#define ENTIRE_DISPLAY_ON()    Write_Instruction(0xa5)   //  Entire dislay   Force whole LCD point
#define ENTIRE_DISPLAY_OFF()   Write_Instruction(0xa4)   //  Normal display
#define SET_BIAS()             Write_Instruction(0xa3)   //  bias 1   1/7 bais
#define CLEAR_BIAS()           Write_Instruction(0xa2)   //  bias 0   1/9 bais
#define RESET()                Write_Instruction(0xe2)	//   system reset
#define SET_SHL()              Write_Instruction(0xc8)   // SHL 1,COM63-COM0
#define CLEAR_SHL()            Write_Instruction(0xc0)   // SHL 0,COM0-COM63

#define Start_column	0x00
#define Start_page		0x00
#define	StartLine_set	0x00

void Delay1(uint n);
void Write_number(uchar code *n,uchar k,uchar station_dot);
void display_Contrast_level(uchar number);
void adj_Contrast(void);
void Delay(uint n);
void Busy();
void Write_Data(unsigned char dat);
void Write_Instruction(unsigned char cmd);
void Initial_Dispay_Line(unsigned char line);
void Set_Page_Address(unsigned char add);
void Set_Column_Address(unsigned char add);
void Power_Control(unsigned char vol);
void Regulor_Resistor_Select(unsigned char r);
void Set_Contrast_Control_Register(unsigned char mod);
void Initial(void);
void Display_Chess(unsigned char value);
void Display_Chinese(unsigned char ft[]);
void Display_Chinese_Column(unsigned char ft[]);
void Display_Picture(unsigned char pic[]);


uchar code	    num[]={0x00,0xF8,0xFC,0x04,0x04,0xFC,0xF8,0x00,0x00,0x03,0x07,0x04,0x04,0x07,0x03,0x00,  	   /*--  文字:  0~9  --*/
0x00,0x00,0x08,0xFC,0xFC,0x00,0x00,0x00,0x00,0x00,0x04,0x07,0x07,0x04,0x00,0x00,  
....
0x00,0x78,0xFC,0x84,0xC4,0xFC,0xF8,0x00,0x00,0x06,0x06,0x04,0x06,0x03,0x01,0x00};

unsigned char code font[]=
{

/*--  文字:  深  --*/
/*--  宋体12;  此字体下对应的点阵为:宽x高=16x16   --*/
0x10,0x61,0x06,0xE0,0x00,0x26,0x22,0x1A,0x02,0xC2,0x0A,0x12,0x32,0x06,0x02,0x00,
0x04,0xFC,0x03,0x20,0x20,0x11,0x11,0x09,0x05,0xFF,0x05,0x09,0x19,0x31,0x10,0x00,

/*--  文字:  圳  --*/
/*--  宋体12;  此字体下对应的点阵为:宽x高=16x16   --*/
0x10,0x10,0x10,0xFE,0x10,0x10,0xFE,0x00,0x00,0xFC,0x00,0x00,0x00,0xFE,0x00,0x00,
0x08,0x08,0x04,0x47,0x24,0x18,0x07,0x00,0x00,0x1F,0x00,0x00,0x00,0x7F,0x00,0x00,

/*--  文字:  旭  --*/
/*--  宋体12;  此字体下对应的点阵为:宽x高=16x16   --*/
0x10,0x10,0x10,0xFF,0x10,0xF0,0x00,0x00,0xFE,0x22,0x22,0x22,0x22,0xFE,0x00,0x00,
0x40,0x30,0x0E,0x01,0x00,0x3F,0x40,0x40,0x47,0x44,0x44,0x44,0x44,0x47,0x70,0x00,

/*--  文字:  日  --*/
/*--  宋体12;  此字体下对应的点阵为:宽x高=16x16   --*/
0x00,0x00,0x00,0xFE,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0xFE,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x3F,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x3F,0x00,0x00,0x00,0x00,

/*--  文字:  东  --*/
/*--  宋体12;  此字体下对应的点阵为:宽x高=16x16   --*/
0x00,0x04,0x04,0xC4,0xB4,0x8C,0x87,0x84,0xF4,0x84,0x84,0x84,0x84,0x04,0x00,0x00,
0x00,0x00,0x20,0x18,0x0E,0x04,0x20,0x40,0xFF,0x00,0x02,0x04,0x18,0x30,0x00,0x00,

/*--  文字:  方  --*/
/*--  宋体12;  此字体下对应的点阵为:宽x高=16x16   --*/
0x08,0x08,0x08,0x08,0x08,0x08,0xF9,0x4A,0x4C,0x48,0x48,0xC8,0x08,0x08,0x08,0x00,
0x40,0x40,0x20,0x10,0x0C,0x03,0x00,0x00,0x20,0x40,0x40,0x3F,0x00,0x00,0x00,0x00,

/*--  文字:  科  --*/
/*--  宋体12;  此字体下对应的点阵为:宽x高=16x16   --*/
0x10,0x12,0x92,0x72,0xFE,0x51,0x91,0x00,0x22,0xCC,0x00,0x00,0xFF,0x00,0x00,0x00,
0x04,0x02,0x01,0x00,0xFF,0x00,0x04,0x04,0x04,0x02,0x02,0x02,0xFF,0x01,0x01,0x00,

/*--  文字:  技  --*/
/*--  宋体12;  此字体下对应的点阵为:宽x高=16x16   --*/
0x08,0x08,0x88,0xFF,0x48,0x28,0x00,0xC8,0x48,0x48,0x7F,0x48,0xC8,0x48,0x08,0x00,
0x01,0x41,0x80,0x7F,0x00,0x40,0x40,0x20,0x13,0x0C,0x0C,0x12,0x21,0x60,0x20,0x00,

/*--  文字:  成  --*/
/*--  宋体12;  此字体下对应的点阵为:宽x高=16x16   --*/
0x00,0x00,0xF8,0x48,0x48,0x48,0xC8,0x08,0xFF,0x08,0x09,0x0A,0xC8,0x88,0x08,0x00,
0x40,0x30,0x0F,0x00,0x08,0x50,0x4F,0x20,0x10,0x0B,0x0C,0x12,0x21,0x40,0xF0,0x00,

/*--  文字:  立  --*/
/*--  宋体12;  此字体下对应的点阵为:宽x高=16x16   --*/
0x00,0x10,0x10,0x90,0x10,0x10,0x11,0x16,0x10,0x10,0xF0,0x50,0x10,0x10,0x00,0x00,
0x40,0x40,0x40,0x40,0x43,0x4E,0x40,0x60,0x58,0x47,0x40,0x40,0x40,0x60,0x40,0x00,

/*--  文字:  于  --*/
/*--  宋体12;  此字体下对应的点阵为:宽x高=16x16   --*/
0x40,0x40,0x42,0x42,0x42,0x42,0x42,0xFE,0x42,0x42,0x42,0x42,0x42,0x42,0x40,0x00,
0x00,0x00,0x00,0x00,0x20,0x40,0x80,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

/*--  文字:  一  --*/
/*--  宋体12;  此字体下对应的点阵为:宽x高=16x16   --*/
0x00,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0xC0,0x80,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

/*--  文字:  九  --*/
/*--  宋体12;  此字体下对应的点阵为:宽x高=16x16   --*/
0x00,0x10,0x10,0x10,0x10,0x90,0x7F,0x10,0x10,0x10,0xF8,0x10,0x00,0x00,0x00,0x00,
0x00,0x40,0x20,0x10,0x0C,0x03,0x00,0x00,0x00,0x00,0x7F,0x40,0x40,0x78,0x20,0x00,

/*--  文字:  九  --*/
/*--  宋体12;  此字体下对应的点阵为:宽x高=16x16   --*/
0x00,0x10,0x10,0x10,0x10,0x90,0x7F,0x10,0x10,0x10,0xF8,0x10,0x00,0x00,0x00,0x00,
0x00,0x40,0x20,0x10,0x0C,0x03,0x00,0x00,0x00,0x00,0x7F,0x40,0x40,0x78,0x20,0x00,

/*--  文字:  七  --*/
/*--  宋体12;  此字体下对应的点阵为:宽x高=16x16   --*/
0x00,0x40,0x40,0x40,0x40,0x40,0x40,0xFE,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x40,0x40,0x40,0x40,0x40,0x38,0x00,0x00,

/*--  文字:  年  --*/
/*--  宋体12;  此字体下对应的点阵为:宽x高=16x16   --*/
0x40,0x20,0x10,0x0C,0xE3,0x22,0x22,0x22,0xFE,0x22,0x22,0x22,0x22,0x02,0x00,0x00,
0x04,0x04,0x04,0x04,0x07,0x04,0x04,0x04,0xFF,0x04,0x04,0x04,0x04,0x04,0x04,0x00,

/*--  文字:  期  --*/
/*--  宋体12;  此字体下对应的点阵为:宽x高=16x16   --*/
0x00,0x04,0xFF,0x54,0x54,0x54,0xFF,0x04,0x00,0xFE,0x22,0x22,0x22,0xFE,0x00,0x00,
0x42,0x22,0x1B,0x02,0x02,0x0A,0x33,0x62,0x18,0x07,0x02,0x22,0x42,0x3F,0x00,0x00,

/*--  文字:  待  --*/
/*--  宋体12;  此字体下对应的点阵为:宽x高=16x16   --*/
0x20,0x10,0x08,0xC7,0x3A,0x50,0x44,0x44,0x44,0x7F,0x44,0xC4,0x44,0x44,0x40,0x00,
0x00,0x02,0x01,0xFF,0x00,0x02,0x02,0x1A,0x02,0x42,0x82,0x7F,0x02,0x02,0x02,0x00,

/*--  文字:  着  --*/
/*--  宋体12;  此字体下对应的点阵为:宽x高=16x16   --*/
0x00,0x44,0x54,0x54,0x55,0x56,0xD4,0x7C,0x54,0x54,0x56,0x55,0x54,0x44,0x44,0x00,
0x08,0x08,0x04,0x04,0x02,0xFF,0x55,0x55,0x55,0x55,0x55,0x55,0xFF,0x00,0x00,0x00,

/*--  文字:  您  --*/
/*--  宋体12;  此字体下对应的点阵为:宽x高=16x16   --*/
0x80,0x40,0x30,0xFC,0x03,0x90,0x68,0x06,0x04,0xF4,0x04,0x24,0x44,0x8C,0x04,0x00,
0x00,0x20,0x38,0x03,0x38,0x40,0x40,0x49,0x52,0x41,0x40,0x70,0x00,0x09,0x30,0x00,

/*--  文字:  来  --*/
/*--  宋体12;  此字体下对应的点阵为:宽x高=16x16   --*/
0x00,0x80,0x84,0x84,0x94,0xA4,0xC4,0xFF,0x84,0xC4,0xB4,0x94,0x84,0x84,0x80,0x00,
0x20,0x20,0x10,0x10,0x08,0x04,0x02,0xFF,0x01,0x02,0x04,0x08,0x18,0x30,0x10,0x00,

/*--  文字:  电  --*/
/*--  宋体12;  此字体下对应的点阵为:宽x高=16x16   --*/
0x00,0x00,0xF8,0x48,0x48,0x48,0x48,0xFF,0x48,0x48,0x48,0x48,0xF8,0x00,0x00,0x00,
0x00,0x00,0x0F,0x04,0x04,0x04,0x04,0x3F,0x44,0x44,0x44,0x44,0x4F,0x40,0x70,0x00,

/*--  文字:  来  --*/
/*--  宋体12;  此字体下对应的点阵为:宽x高=16x16   --*/
0x00,0x80,0x84,0x84,0x94,0xA4,0xC4,0xFF,0x84,0xC4,0xB4,0x94,0x84,0x84,0x80,0x00,
0x20,0x20,0x10,0x10,0x08,0x04,0x02,0xFF,0x01,0x02,0x04,0x08,0x18,0x30,0x10,0x00,

/*--  文字:  函  --*/
/*--  宋体12;  此字体下对应的点阵为:宽x高=16x16   --*/
0x00,0xE0,0x02,0x12,0xE2,0x42,0x02,0xF2,0x12,0x8A,0x66,0x47,0x02,0xE0,0x00,0x00,
0x00,0x7F,0x20,0x24,0x24,0x2A,0x31,0x2F,0x21,0x22,0x24,0x2C,0x20,0x7F,0x00,0x00,

/*--  文字:  我  --*/
/*--  宋体12;  此字体下对应的点阵为:宽x高=16x16   --*/
0x20,0x20,0x22,0x22,0xFE,0x21,0x21,0x20,0x20,0xFF,0x20,0x22,0xAC,0x20,0x20,0x00,
0x04,0x04,0x42,0x82,0x7F,0x01,0x01,0x10,0x10,0x08,0x07,0x1A,0x21,0x40,0xF0,0x00,

/*--  文字:  们  --*/
/*--  宋体12;  此字体下对应的点阵为:宽x高=16x16   --*/
0x80,0x40,0xF0,0x1C,0x03,0xF0,0x01,0x0E,0x04,0x00,0x04,0x04,0x04,0xFC,0x00,0x00,
0x00,0x00,0x7F,0x00,0x00,0x7F,0x00,0x00,0x00,0x00,0x00,0x20,0x40,0x3F,0x00,0x00,

/*--  文字:  真  --*/
/*--  宋体12;  此字体下对应的点阵为:宽x高=16x16   --*/
0x00,0x04,0x04,0x04,0xF4,0x54,0x5C,0x57,0x54,0x54,0x54,0xF4,0x04,0x06,0x04,0x00,
0x10,0x90,0x90,0x50,0x5F,0x35,0x15,0x15,0x15,0x35,0x55,0x5F,0x90,0x90,0x10,0x00,

/*--  文字:  诚  --*/
/*--  宋体12;  此字体下对应的点阵为:宽x高=16x16   --*/
0x20,0x21,0xE6,0x02,0x08,0xF8,0x88,0x88,0x88,0x08,0xFF,0x08,0x0A,0xCC,0x88,0x00,
0x00,0x00,0x3F,0x90,0x68,0x1F,0x20,0x40,0x3F,0x20,0x10,0x0F,0x14,0x23,0x78,0x00,

/*--  文字:  为  --*/
/*--  宋体12;  此字体下对应的点阵为:宽x高=16x16   --*/
0x00,0x10,0x10,0x12,0x14,0x1C,0x10,0xF0,0x9F,0x10,0x10,0x10,0x10,0xF8,0x10,0x00,
0x00,0x00,0x40,0x20,0x10,0x08,0x06,0x01,0x00,0x11,0x26,0x40,0x20,0x1F,0x00,0x00,

/*--  文字:  您  --*/
/*--  宋体12;  此字体下对应的点阵为:宽x高=16x16   --*/
0x80,0x40,0x30,0xFC,0x03,0x90,0x68,0x06,0x04,0xF4,0x04,0x24,0x44,0x8C,0x04,0x00,
0x00,0x20,0x38,0x03,0x38,0x40,0x40,0x49,0x52,0x41,0x40,0x70,0x00,0x09,0x30,0x00,

/*--  文字:  服  --*/
/*--  宋体12;  此字体下对应的点阵为:宽x高=16x16   --*/
0x00,0x00,0xFF,0x91,0x91,0xFF,0x00,0x00,0xFF,0xC1,0x41,0x49,0x51,0xCF,0x00,0x00,
0x40,0x30,0x0F,0x20,0x40,0x3F,0x00,0x00,0x7F,0x21,0x16,0x08,0x36,0x61,0x20,0x00,

/*--  文字:  务  --*/
/*--  宋体12;  此字体下对应的点阵为:宽x高=16x16   --*/
0x20,0x10,0x10,0x88,0x84,0x4F,0x52,0xA2,0x22,0x52,0x4A,0x86,0x80,0x80,0x80,0x00,
0x80,0x81,0x41,0x42,0x22,0x12,0x0E,0x03,0x02,0x42,0x82,0x7E,0x00,0x01,0x00,0x00

};

unsigned char code pic[]=
{/*--  调入了一幅图像:D:\产品文件\显示图片\ERM12864-655.bmp  --*/
/*--  宽度x高度=128x64  --*/
0xFF,0x01,0x01,0xF1,0x91,0x91,0x91,0x91,0x01,0x81,0x61,0x11,0x61,0x81,0x01,0x61,
0x91,0x91,0x21,0x01,0x11,0x11,0xF1,0x11,0x11,0x01,0xF1,0x91,0x91,0x91,0x61,0x01,
0x01,0xF1,0x01,0x01,0x61,0x91,0x91,0x21,0x01,0x01,0xF1,0x01,0x01,0xF1,0x61,0x81,
0x01,0xF1,0x01,0x01,0xE1,0x11,0x11,0x91,0xA1,0x01,0x01,0x01,0x01,0x11,0x11,0xF1,
0x11,0x11,0x01,0xF1,0x91,0x91,0x91,0x91,0x01,0xE1,0x11,0x11,0x11,0x21,0x01,0x01,
0xF1,0x81,0x81,0x81,0xF1,0x01,0x01,0x01,0x01,0x01,0xE1,0x11,0x11,0x11,0x21,0x01,
....
0xBC,0x80,0x80,0xA0,0x80,0x9C,0xA2,0xA2,0xA2,0x9C,0x80,0x9C,0xA2,0xA2,0x94,0x80,
0xBE,0x82,0x82,0xBC,0x82,0x82,0xBC,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0xFF


};

unsigned char code pic1[]=
{/*--  调入了一幅图像:D:\liu\显示图片\12864LOGO.bmp  --*/
/*--  宽度x高度=128x64  --*/
0xFF,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,
0x01,0x01,0x01,0xC1,0xE1,0xF1,0xFD,0xFF,0xFF,0xFD,0x01,0x61,0xF1,0xE1,0xE1,0xE1,
....
0x91,0xA0,0xA0,0xA0,0xA0,0xA0,0xA0,0x90,0x8F,0x87,0x80,0x80,0x80,0x80,0x80,0x80,
0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0xFF

};

unsigned char code pic2[]=
{

/*--  调入了一幅图像:D:\liu\显示图片\128642.bmp  --*/
/*--  宽度x高度=128x64  --*/
0xFF,0x01,0x01,0x01,0x01,0x01,0x01,0xC1,0xF1,0xFD,0xFD,0x81,0x01,0x01,0x01,0x01,
....
0x82,0x81,0xBD,0xA2,0xA2,0xB9,0xA7,0x90,0xB2,0x8F,0x83,0x82,0xB9,0xA7,0x80,0xB8,
0xA6,0xA1,0xB1,0xAF,0x90,0x80,0xBC,0xA2,0xA2,0xB9,0xA7,0x90,0x80,0x80,0x80,0xFF

};


unsigned char code pic3[]=
{
/*--  调入了一幅图像:D:\liu\显示图片\12864a.bmp  --*/
/*--  宽度x高度=128x64  --*/
0x08,0x02,0x00,0xF0,0x0F,0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0xEF,0x30,0x18,0x0E,
0x04,0x02,0x03,0x01,0x00,0x00,0x08,0x1C,0x0C,0x06,0xA3,0xF1,0x70,0x78,0x3C,0xBE,
0x17,0x9B,0xCB,0x8D,0xC5,0x67,0x63,0xE1,0xF1,0x70,0x10,0x04,0xC2,0x70,0x18,0x8C,
0x0C,0x08,0xD0,0x30,0x8C,0x42,0xB0,0x48,0x24,0x02,0x01,0x00,0x60,0x0C,0x00,0x00,
....
0x03,0x03,0x07,0x07,0x07,0x07,0x07,0x01,0x00,0x00,0x00,0x00,0x30,0x3F,0x00,0x00,
0x00,0x00,0xF0,0x0E,0x01,0x80,0xE0,0x18,0x06,0x81,0xE0,0xF8,0xFE,0xFF,0x7D,0xC7,
0xF3,0xFB,0x7F,0x07,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x1E,0xFC,0xC1,0x0A
};

unsigned char code pic4[]=
{/*--  调入了一幅图像:D:\liu\显示图片\12864-.bmp  --*/
/*--  宽度x高度=128x64  --*/
0x80,0xF0,0xFC,0xFF,0x7F,0x0F,0x07,0x21,0xF4,0x00,0x00,0x80,0x80,0x80,0xC0,0xC0,
....
0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x08,0x18,0x0C,0x0F,0x00,0x03,
0x02,0x02,0x0F,0x02,0x02,0x02,0x00,0x1F,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00
};


void Step(void) interrupt 0 using 0
{
	Delay1(300);
	if(int0==0)	log=!log;
   while(!int0);
  return;

}


void Delay1(uint n)
{while(n--);
   
	return;
}


void Write_number(uchar code *n,uchar k,uchar station_dot)
{uchar i; 
			for(i=0;i<8;i++)
				{
				Write_Data(*(n+16*k+i));
				}
				
	Set_Page_Address(Start_page+1)	;
	Set_Column_Address(Start_column+station_dot*8);	
			for(i=8;i<16;i++)
				{
				Write_Data(*(n+16*k+i));
				}
}



void display_Contrast_level(uchar number)
{	uchar number1,number2;
	number1=number/10;number2=number%10;
	Initial_Dispay_Line(0x00);
	Set_Column_Address(Start_column+0*8);
	Set_Page_Address(Start_page);
	Write_number(num,number1,0);
	Set_Column_Address(Start_column+1*8);
	Set_Page_Address(Start_page);
	Write_number(num,number2,1);

}


void adj_Contrast(void)
{	Delay1(300);
	 if((key_add==0)||(key_dec==0))
		{		
		 if	(key_add==0) 
			{Contrast_level+=1; if(Contrast_level>0x3f)(Contrast_level=0);
			Set_Contrast_Control_Register(Contrast_level);	
			display_Contrast_level(Contrast_level);
			Delay1(18000);
			if(key_add==0)
				{Delay1(18000);
					if(key_add==0)			
						{Delay1(18000);
							if(key_add==0)
								{Delay1(18000);
									if(key_add==0)

										{while(key_add==0)
											{Contrast_level+=1; if(Contrast_level>0x3f)(Contrast_level=0);
												Set_Contrast_Control_Register(Contrast_level);	
												display_Contrast_level(Contrast_level);
												Delay1(20000); 
											}
										}
								}				
						}						
				}												
			}
	


		  
	
		 if	(key_dec==0) 
			{Contrast_level-=1; if((Contrast_level<=0xff)&&(Contrast_level>0x3f))(Contrast_level=0x3f);
			Set_Contrast_Control_Register(Contrast_level);	
			display_Contrast_level(Contrast_level);
			Delay1(18000);
			if(key_dec==0)
				{Delay1(18000);
					if(key_dec==0)			
						{Delay1(18000);
							if(key_dec==0)
								{Delay1(18000);
									if(key_dec==0)

										{while(key_dec==0)
											{Contrast_level-=1; if((Contrast_level<=0xff)&&(Contrast_level>0x3f))(Contrast_level=0x3f);
												Set_Contrast_Control_Register(Contrast_level);	
												display_Contrast_level(Contrast_level);
												Delay1(20000); 
											}
										}
								}				
						}						
				}												
			}

		}
}


void Delay(uint n)
{while(n)
 {    if((key_add==0)||(key_dec==0)) adj_Contrast();
	  n--;
 }
	for(;log==1;)
	{
	 if((key_add==0)||(key_dec==0)) adj_Contrast();
	}

	return;
}



#if (TIMING==8080)

#pragma disable
void Busy()
{
	unsigned char flag=0xff;
	RS=0;E_RD=1;RW_WR=1;
	while ((flag&0x80)==0x80)
	{
		E_RD=0;
		_nop_();
		flag=DATA_BUS;
		E_RD=1;
	}
	return;
}

#else

#pragma disable
void Busy()
{
	unsigned char flag=0xff;
	RS=0;E_RD=0;RW_WR=1;
	while ((flag&0x80)==0x80)
	{
		E_RD=1;
		_nop_();
		flag=DATA_BUS;
		E_RD=0;
	}
	return;
}

#endif


#if (TIMING==8080)

#pragma disable 
void Write_Data(unsigned char dat)
{
	Busy();
	RS=1;

	RW_WR=0;
	DATA_BUS=dat;
	_nop_();
	RW_WR=1;
	return;
}

#else

#pragma disable
void Write_Data(unsigned char dat) 
{
	Busy();
	RS=1;
	RW_WR=0;
	DATA_BUS=dat;
	E_RD=1;
	_nop_();
	E_RD=0;
	return;
}

#endif



#if (TIMING==8080)

#pragma disable
void Write_Instruction(unsigned char cmd)
{
	Busy();
	RS=0;

	RW_WR=0;
	DATA_BUS=cmd;
	_nop_();
	RW_WR=1;
	return;
}

#else

#pragma disable
void Write_Instruction(unsigned char cmd)
{
	Busy();
	RS=0;
	RW_WR=0;
	DATA_BUS=cmd;
	E_RD=1;
	_nop_();
	E_RD=0;
	return;
}

#endif

//Specify DDRAM line for COM0 0~63
void Initial_Dispay_Line(unsigned char line)
{
	line|=0x40;
	Write_Instruction(line);
	return;
}


// Set page address 0~15
void Set_Page_Address(unsigned char add)
{
	add=0xb0|add;
	Write_Instruction(add);
	return;
}

void Set_Column_Address(unsigned char add)
{
	Write_Instruction((0x10|(add>>4)));
	Write_Instruction((0x0f&add+0x04));
	return;
}


// Power_Control   4 (internal converte ON) + 2 (internal regulor ON) + 1 (internal follower ON)


void Power_Control(unsigned char vol)
{
	Write_Instruction((0x28|vol));
	return;
}

/*  Regulor resistor select
**            1+Rb/Ra  Vo=(1+Rb/Ra)Vev    Vev=(1-(63-a)/162)Vref   2.1v
**            0  3.0       4  5.0(default)
**            1  3.5       5  5.5
**            2  4         6  6
**            3  4.5       7  6.4
*/
void Regulor_Resistor_Select(unsigned char r)
{
	Write_Instruction((0x20|r));
	return;
}

//a(0-63) 32default   Vev=(1-(63-a)/162)Vref   2.1v
void Set_Contrast_Control_Register(unsigned char mod)
{
	Write_Instruction(0x81);
	Write_Instruction(mod);
	return;
}


#pragma disable
void Initial(void)
{
	RESET();
	RST=1;
	Delay(2000);
	RST=0;
	Delay(2000);
	RST=1;

	Delay(10000);
	CS1=0;
	SET_ADC();
	CLEAR_SHL();
	CLEAR_BIAS();
	Power_Control(0x07);
	Regulor_Resistor_Select(0x06);
	Set_Contrast_Control_Register(Contrast_level);
	Initial_Dispay_Line(0x00);
	DISPLAY_ON();
}


void Display_Chess(unsigned char value)
{
	unsigned char i,j,k;
	for(i=0;i<0x08;i++)
	{
		Set_Page_Address(i);

		Set_Column_Address(0x00);

		for(j=0;j<0x10;j++)
		{
			for(k=0;k<0x04;k++)
				Write_Data(value);
			for(k=0;k<0x04;k++)
				Write_Data(~value);
		}
	}
	return;
}


void Display_Chinese(unsigned char ft[])
{
	unsigned char i,j,k,b,c=0;
	unsigned int	num=0;

for(b=0;b<4;b++)
  {
	for(i=0;i<0x02;i++)
	{	Set_Page_Address(c);
		Set_Column_Address(0x00);
		num=i*0x10+b*256;
		for(j=0;j<0x08;j++)
		{
			for(k=0;k<0x10;k++)
			{
				Write_Data(ft[num+k]);
			}
			num+=0x20;
		}c++;
	}
  }
	return;
}


//Display_Chinese1
void Display_Chinese_Column(unsigned char ft[])
{
	unsigned char i,j,k,num=0x40;
	Initial_Dispay_Line(0x40);
	for(i=0;i<0x08;i++)
	{
		Set_Page_Address(i);
		Set_Column_Address(0x00);
		for(j=0;j<0x08;j++)
		{
			for(k=0;k<0x10;k++)
			{
				Write_Data(ft[num+k]);
			}
		}
	num+=0x10;
	}
	return;
}


void Display_Picture(unsigned char pic[])
{
	unsigned char i,j,num=0;
	Initial_Dispay_Line(0x40);
	for(i=0;i<0x08;i++)
	{
	Set_Page_Address(i);
	Set_Column_Address(0x00);
		for(j=0;j<0x80;j++)
		{
			Write_Data(pic[i*0x80+j]);
		}
	}
	return;
}



void main(void)
{	IE=0x81;
	IP=0x01;
	TCON=0x01;
//	EA=1;
//	EX0=1;
//	IT0=1;
//	IE0=0;
	int0=1;
	Delay(1000);
	CS1=0;
	Initial();
	Delay(1000);
	REVERSE_DISPLAY_OFF();
	ENTIRE_DISPLAY_OFF();
	while(1)
	{
		Display_Picture(pic);
		Delay(65000);
		Delay(65000);
		REVERSE_DISPLAY_ON();
		Delay(65000);
		Delay(65000);
		REVERSE_DISPLAY_OFF();

		Display_Picture(pic1);
		Delay(65000);
		Delay(65000);
		REVERSE_DISPLAY_ON();
		Delay(65000);
		Delay(65000);
		REVERSE_DISPLAY_OFF();

		Display_Picture(pic2);
		Delay(65000);
		Delay(65000);
		REVERSE_DISPLAY_ON();
		Delay(65000);
		Delay(65000);
		REVERSE_DISPLAY_OFF();

		Display_Picture(pic3);
		Delay(65000);
		Delay(65000);
		REVERSE_DISPLAY_ON();
		Delay(65000);
		Delay(65000);
		REVERSE_DISPLAY_OFF();

		Display_Picture(pic4);
		Delay(65000);
		Delay(65000);
		REVERSE_DISPLAY_ON();
		Delay(65000);
		Delay(65000);
		REVERSE_DISPLAY_OFF();

		Display_Chess(0x0f);
		Delay(65000);
		Delay(65000);
		REVERSE_DISPLAY_ON();
		Delay(65000);
		Delay(65000);
		REVERSE_DISPLAY_OFF();
		Display_Chinese(font);
		Delay(65000);
		Delay(65000);
		REVERSE_DISPLAY_ON();
		Display_Chinese(font);
		Delay(65000);
		Delay(65000);
		REVERSE_DISPLAY_OFF();
		Display_Chinese_Column(font);
		Delay(65000);
		Delay(65000);
		REVERSE_DISPLAY_ON();
		Display_Chinese_Column(font);
		Delay(65000);
		Delay(65000);
		REVERSE_DISPLAY_OFF();
	}
}

One of the beautiful things about C++ is that usually you can have both.

For example, SDL2 actually defines macros to support alternative spellings (which would be type aliases if it were C++ rather than just C).

Interestingly I think if I were to do a find-replace to replace all the American spellings in the Arduboy2 library it would only actually break two functions and one variable, and only if a game was actually using those.
Everything else would be fine because it’s either a function parameter, a local variable or just part of the documentation.

Either way, your documentation doesn’t have to match the API’s spelling.
The API is set in stone, the documentation is more flexible.

At any rate, I’ll let it slide this time. :P

That’s the easy bit mostly done then.

Getting buttons working in the library should just be a matter of changing the pin mappings, the button state reading, and possibly some of the pin boot code.

I won’t look into that now because it’s late,
but I might have a look tomorrow if I have time.

With any luck it’ll just be a matter of writing to some specific registers and there should already be some Arduino support for it.

Though SAMD doesn’t always get the support that the AVR-based chips do.

That’s the sort of thing I was expecting, but I thought I’d better check.
Quartz crystals get used for quite a few things.

In that case ‘unconnected’ or ‘unassigned’ would probably have been a better description.
It threw me a bit because only three pins are marked as ‘floating’ and some of the pins described as ‘not connected’ in the ‘type’ column just had a ‘-’ in ‘default logic state’ so I thought it meant something special.

Sometimes I question who comes up with the tech terminology, there’s lots of daft decisions floating around. :P

Yeah, that’s the sort of thing that would work.
It’ll probably only take one of them to provide decent results.

Don’t worry about it too much.
Finalising the hardware is more important,
and I’ll still have to know how to interface with these ports before I could contribute anything useful.

The source for that program with the buttons being pressed and the LED lighting up would probably be more useful at the moment anyway.

I just did a search of ‘SWD’ to find out what it might be an acronym for and that seemed the most likely candidate.
It wasn’t a term I was familiar with at all (though I have heard of JTAG).

It seems I missed parts of that column because I was zoomed in and flicking around from area to area.
I also overlooked the cells with the comments about the infrared.

IR is really underrated.

It’s not particularly useful for real-time data transmission,
but it’s decent enough for infrequent transmissions like you’d find in turn-based games.

Tamagotchi made use of it, and I’m pretty sure Pokemon would have worked over IR.

If there’s a way to reliably transfer bits and/or bytes then the only real challenge is a good design for the data transfer protocol.

I think most IR protocols are application-specific.
Even TVs don’t run on a single unified protocol, different manufacturers have different command sets.

Fortunately there’s no shortage of IR-based libraries to look to for examples.

Unfortunately, few actually document the protocols in a nice way,
so it would either be a case of ignoring all existing protocols and coming up with something new,
or tediously picking apart other people’s uncommented code.

Which has been succeeded by u8g2.

I have a tiny bit of experience with u8g2.
The sad truth is that the C++ interface is nothing more than a thin wrapper around the C code,
and u8glib is no exception.

I could pick them both apart and they may come in handy,
but there’s something more far important to discuss…

Bits and pieces are useful.

The adj_Contrast function is frankly disturbing.
It’s splattered with non-standard stuff (e.g. interrupt 0 using 0, sbit, bit, #pragma disable),
and most of it is just the standard “throw command bytes at the display over SPI”.
(Though the specific register writing might be useful or important.)

However…

In amongst all that crap is the single most important thing out of all the code you’ve just thrown at me…

The chinese font data!

Why?

Chinese.hex (22.6 KB)

https://gist.github.com/Pharap/cf4b9f13b3a155ebf6ace948c523f86b

Still confused?

In case the implications of this are too subtle:
If that demo program from the LCD manufacturer definitely works on the UC1701 then this proves that it has the same frame buffer layout as the Arduboy, which was the missing piece of the puzzle and means this is probably going to be relatively easy to pull off.

1 Like

Just Wow. I know it seems simple but that’s what I really love about that little test you did there. Thanks so much for looking at this.

Next version of the pinout table:


Should just be the additional column to separate out Input/Output from Analog/Digital. BTW, the colour coding has blue for Port A and Green for Port B. I have too often missed that something is PB## rather than PA## because I just assumed everything would be on that. Hyphens are meant to indicate the cell is intentionally blank, rather than an empty cell which indicates I have omitted putting something in there.

Thanks for the tip - I do know u8g2 has succeeded it but I thought the original library was likely to have fewer layers of abstraction because it was trying to serve fewer controllers and displays, so might be easier to find the specifics for the UC1701.

I’m glad I’m not the only one who thinks so!

Yes, I had to sniff the protocol on our remote when I wanted to use it as the D pad for the robots I built my children.

BTW, ref the joystick, I desoldered it this evening and put it on the “correct” way round. Fortunately, it now works without needing to depress the centre button at the same time as changing direction (centre button and common pads were swapped when soldered on the wrong way!). The bad news is that somehow I have lined it up 180 degrees out of kilter. This makes up = down and left = right… The D pad buttons work fine and I will revise in a future board spin. I love the feel of that joystick though. Waaay better than my rubbish tactile switches and you can click in different directions really quickly because there’s so little travel from one side to another.

Have a good rest and I hope to catch up with you soon.

1 Like

Sometimes the dumbest solutions are the best.

“I choose a lazy person to do a hard job. Because a lazy person will find an easy way to do it.” - Bill Gates

In all honesty I only thought of doing it in the first place because I was being too lazy to sit through and read all the code - I was actively looking for an easy solution. :P

(Programming is first and foremost about problem solving after all.)

Remind me, what are the ports?

I’m assuming they’re just a collection of pins,
but I’m used to there being 8 pins per port for AVR chips (unless I’ve misread the labels),
and yet here there seems to be more.

:P

Perhaps. I’ll have a look into it tomorrow, though it’s probably not going to be needed unless there’s some particularly interesting combinations of instructions.

For controlling the screen the only complicated parts are booting it, sleeping it, possibly setting the data ‘cursor’ and finding out how to interact with it in the first place.

Most of the commands are pretty simple.
It’s usually just a matter of throwing a byte or two at it over SPI.
For example, inverting the display (so white renders as black and vice versa) should be something along the lines of:

LCD_CD = 0;
LCD_WR = 0;
SPITransfer(0x53);

(Or something like that - it depends on what the APIs are like for sending data to the screen.)

I’ve previously considered building a ‘sonic screwdriver’ that would basically just be an IR remote so I could do stuff like turn off lights in my room without having to get up.

Like many things the idea fell to the wayside.

I found a pretty decent library for that sort of thing once,
but I don’t think I bookmarked it, or if I did I can’t find where I put it.

Ah, you must be one of those ‘cool’ parents I hear about.
My dad never built me a robot…

(If my parents ever had anything that needed to be assembled they’d usually get me to do it.:P)

I’ve always known that’s a possibility but never known anyone who’s actually done it before. :P

As someone who uses an XBox360 controller for various Steam games, I can believe it.

Oh yeah, sleep, I knew there was something I was supposed to be doing… :P

2 Likes

SWD stands for “Serial Wire Debug”

https://en.wikipedia.org/wiki/JTAG#Serial_Wire_Debug

Yes, that’s the exact same article that I linked to - that’s what my search found.