The hardware version will be "slightly delayed", as in probably never done. My soldering skills on a perfboard are not that great, and I have misinterpreted the pinout of the chip.
Initializing the SPI
In the simulation it was sufficient to
; Set MOSI and SCK output, all others input ldi r17,(1<<DD_MOSI)|(1<<DD_SCK) out DDR_SPI,r17 ; Enable SPI, Master, set clock rate fck/4 ldi r17,(1<<SPE)|(1<<MSTR) out SPCR,r17
which is more or less what the ATmega datasheets gives as example.
In RealLife® it is not that simple. I discovered that the Arduino itself would hang every now and then when putting data on the SPI (and that took a long to debug - never seen it do that before). It did so whether something was connected or not. If I used the library
SPI.begin()
it would not hang. (I had other issues with my circuit, so not everything worked, but a) the Arduino did not hang and b) the few LEDs I did control where behaving as expected) It did not matter whether I used a pure C that did direct port access to initialize or assembly.
I got the assembly listing from the generated C code with SPI.begin(), and the proper way to setup the SPI seems to be
; set pin 10 high,to avoid an initial pulse in Tmp,PORTB ori Tmp,0B00000100 ; pin 10 out PORTB,Tmp ; now set it output in Tmp,DDRB ori Tmp,0B00000100 ; pin 10 out DDRB,Tmp ; Set the SPI controls (needs to be two seperate setting of one bit each?!) in Tmp,SPCR ori Tmp,0b01000000 ; "SPCR |= (1<<SPE);" out SPCR,Tmp in Tmp,SPCR ori Tmp,0b00010000 ; "SPCR |= (1<<MSTR);" out SPCR,Tmp ; Now set the 11 and 13 as output in Tmp,DDRB ori Tmp,0b00101000 out DDRB,Tmp
That initializes the SPI port without problems ("Tmp" is a synonym for r16)
Afterwards, one has to send SPI commands to the chips to initialize them, this is kindly pointed out in the notes for the project: following sequence of commands: 0f 00
0b 07
0c 01
The first byte is the "row number" of the matrix, but that only goes to 8, so 9-F addresses an internal register in the chip that configures it. In my case this meant the initialization, after the SPI was initialized, continues with
; Initialize the chip(s) from their startup state cbi PORTB,CSS ; Trigger a "new transaction" on MAX7219 (pin 10 LOW) ldi Tmp2,0x0C ; powersave register: mov Tmp3,One ; 1 = Power UP rcall SendTwo ldi Tmp2,0x0F ; testmode register clr Tmp3 ; 0 = normal operation rcall SendTwo ldi Tmp2,0x09 ; decode mode register rcall SendTwo ; 0 = binary passthrough ldi Tmp2,0x0B ; scan mode register ldi Tmp3,0x07 ; up to 7th, ie all 8 digits(=rows) rcall SendTwo ldi Tmp2,0x0B ; intensity register ldi Tmp3,0x07 ; 4 = quarter intensity rcall SendTwo
The SendTwo
routine just sends the bytes from Tmp2 and Tmp3 on the SPI and waits for completion. Oh, and this only for one chip, I was going to implement a "SendFour" which would duplicate the bytes so both chip (the SPI is daisychained) get the same commands.
The Real Hardware
I screwed up here, a little to eager, and mixed up a few pinouts. The board worked for a while, with only a few matrix row/columns connected, (with the Pong code!) so I know the initialization works, but when fully populating it something happened and I probably will buy a readymade board rather than new Max7219 chips (the throughhole versions are not cheap)
Over-and-Out
Discussions
Become a Hackaday.io Member
Create an account to leave a comment. Already have an account? Log In.