Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AVR128DA48 nano every pinout #464

Open
cristofercruz opened this issue Aug 1, 2023 · 5 comments
Open

AVR128DA48 nano every pinout #464

cristofercruz opened this issue Aug 1, 2023 · 5 comments
Labels
Design Decision This cannot be addressed without making a difficult design decision.

Comments

@cristofercruz
Copy link

Any chance you would consider adding a board variant for the AVR128DA48 to match Arduino Nano Every pinout? I would like to use this chip as an anternative to the 4809/Nano Every on an existing project, not mine (https://github.com/xx0x/gbpxl).

MegaCoreX for the 4809 has a board variant like this: https://github.com/MCUdude/MegaCoreX/tree/master/megaavr/variants/nano-every Considering the chip pins for the AVR128DA48 and ATmega4809 are compatible it seems doable.

I actually gave it a shot here at my end comparing the MegaCoreX standard vs Nano Every variants and applying similar changes to DxCore but only got it partially working. My code seems to execute correctly but something was off with serial output. I need to output to Serial1 (nano every has this mapped to PC4-PC7) and couldn't seem to get any output.

@SpenceKonde
Copy link
Owner

You need to do Serial1.swap(1) to select the alternate pins. They only break out pins for one of the parts

I can say with certainty that I will not create any such variant. The nano every is IMHO the worst official board based on an AVR processor (possibly among arduino boards of other architectures too, but I'm only qualified to comment on AVR). They had finally done it! They picked a modern top notch AVR. They did castelated pads (No, I'm totally not jealous that they can get castellated pads and the board house I like won't do those). All they had to do is get a port of optiboot thrown together, stick a ch340 on it, and badabing! And they did it for ten bucks each. What could possibly be the problem?

Except they lobotomized the processor with a mindblowingly bad pinout. I do not think I could come up with a pinout that more adversely impacted the capability of the board than what they did it's like they tried to see how much capability they could destroy by taking away 13 or so I/O pins. . They put in that unholy jtag2updi thing instead of using a bootloader. The root cause of all the problems was that they kneel before the ancient ATmega328p, and feel that it makes sense to make a 4809 act like a 328p.

I would consider merging a well tested variant someone else created, though I've been trying to hold the line on pin mappings because, well, just look at ATTinyCore, with 2-3 pin mappings on several parts. Once a pinmapping has been released, you cannot get rid of it - you can only add more pinmappings, you can never remove them, otherwise people gather outside your home with torches and pitchforks. The pinmappings are dramatically different between the one obviously correct way to order the pins (PA0, then PA1, PA2 and so on) and the crap that Arduino gave us. They seem to have tried to find at least one critical pin on every peripheral and peripheral portmux and left it unbroken out. It's a terrible disgrace to see a capable part like the 4809 dragged down into the mud like that.

@SpenceKonde
Copy link
Owner

There might also be problems with pin detection for serial - the serial implementation achieves a major optimizatiion by taking advantage of the fact that RX is always the next pin after TX. I'm going to need to special case the EBs if they are to support the UPDI/Reset pin as TX/RX mapping - it has the pins in opposite order.

@SpenceKonde
Copy link
Owner

SpenceKonde commented Aug 3, 2023

Yeah, I checked it uses all arduino pin numbers, and relies on RX = TX+1 (though since TX is the one that we more likely need to set the mode of (all pins start input, so if we haven't been doing things with it it the only problem is that we just set some other pins somewhere else to input. We don't like talking about the arduino pin numbers - on classic avr, that's because of the pin mapping proliferation. On modern ones? Because 1) some of the mappings are swiss cheese - We don't skip every pin number that doesn't appear, because this makes things easier internally, and 2) The dac is on PD6 on every part that has a DAC from Dx/Ex. If we use a number, it will only work on one pincount. (except where we have ghost pins, which happen to fix this, though that's not the purpose) But if we use PIN_PD6, and DAC0 is defined, we would expect to see analog output on PD6! The same is true of every other peripheral. They add mappings, but as yet they have not removed any mappings that were present in an earlier product in the same genus (tinyAVR or fullsize) . We only look up two pin numbers - TX and XCK; that was how we implemented support for more than one swap level (it was a total rewrite). The one DD pincount that had an issue was special-cased, will do same with EB.And with virtually no exceptions RX is on the following pin in the same port. The cool thing is it builds the table from the variant file! Previously, everything had required double, triple, and quadruple entry bookkeeping, and that made the variant files, for say, the 64-pin parts with 6 USARTs even with only two mappings each, tedious

Old way: Variant would have

    #define HAVE_HWSERIAL0                  1
    #define HWSERIAL0_DRE_VECTOR            USART0_DRE_vect
    #define HWSERIAL0_DRE_VECTOR_NUM        USART0_DRE_vect_num
    #define HWSERIAL0_RXC_VECTOR            USART0_RXC_vect
    #define HWSERIAL0                       &USART0
    #define HAVE_HWSERIAL1                  1
    #define HWSERIAL1_DRE_VECTOR            USART1_DRE_vect
    #define HWSERIAL1_DRE_VECTOR_NUM        USART1_DRE_vect_num
    #define HWSERIAL1_RXC_VECTOR            USART1_RXC_vect
    #define HWSERIAL1                       &USART1
    #define HAVE_HWSERIAL2                  1
    #define HWSERIAL2_DRE_VECTOR            USART2_DRE_vect
    #define HWSERIAL2_DRE_VECTOR_NUM        USART2_DRE_vect_num
    #define HWSERIAL2_RXC_VECTOR            USART2_RXC_vect
    #define HWSERIAL2                       &USART2
    #define HAVE_HWSERIAL3                  1
    #define HWSERIAL3_DRE_VECTOR            USART3_DRE_vect
    #define HWSERIAL3_DRE_VECTOR_NUM        USART3_DRE_vect_num
    #define HWSERIAL3_RXC_VECTOR            USART3_RXC_vect
    #define HWSERIAL3                       &USART3
    #define HAVE_HWSERIAL4                  1
    #define HWSERIAL4_DRE_VECTOR            USART4_DRE_vect
    #define HWSERIAL4_DRE_VECTOR_NUM        USART4_DRE_vect_num
    #define HWSERIAL4_RXC_VECTOR            USART4_RXC_vect
    #define HWSERIAL4                       &USART4
    #define HAVE_HWSERIAL5                  1
    #define HWSERIAL5_DRE_VECTOR            USART5_DRE_vect
    #define HWSERIAL5_DRE_VECTOR_NUM        USART5_DRE_vect_num
    #define HWSERIAL5_RXC_VECTOR            USART5_RXC_vect
    #define HWSERIAL5                       &USART5

Instead the core checks if each USART is defined and adds that block of defines of so,

Of course, you do still specify the pins.

OH!! I remember the shortcut we took! pinMode won't work - but also, neither will pins()! Because except where we special case it, pins checks that TX +1 = RX, and that the TX pin is a pin that exists in the table as a TX pin (we mark entries without a TX or RX pin as unavailable). So if the TX doesn't preceed RX pin in number by 1 (which they do except for one non-functional mapping on the DD14/20), pins() is gone. Swap() I think is still there, because we don't check that TX + 1 = RX while building the table, only (I think) in pins as a way to reduce the overhead of that method, which I do not like.,

@cristofercruz
Copy link
Author

Got it, a working nano every pinout is a bit much for me to try implementing on my own. Appreciate the thoughtful feedback though! Knowing this isn't feasible at least pushes me to consider other options. 😄

@SpenceKonde SpenceKonde added the Design Decision This cannot be addressed without making a difficult design decision. label Aug 4, 2023
@SpenceKonde
Copy link
Owner

Serial1.swap(1) may in fact do it on your nano pinout (must be called before begin). Probably follow by setting pinmode of TX to output and of RX to INPUT because like I said, I don't think that's handled correctly. And by doing that before you set up other pins in numeric proximity to that one... then begin()

Lots of peripherals are swapped there. Also, as you may be aware, the two TWI's split up the pinsets that the mega0 had, in addition to bringing some new ones. (with SPI it doesn;'t matter if it's SPI0 or SPI1 - there is only one SPI, and the API lets you swap() to either SPI0 or SPI1 pin mappings. The problem is that the only benefit of two SPI's is if you were compatible with the few dual-SPI compatible arduino libraries. But you can't do that - If they see NUM_SPI_INTERFACES = 2, they expect the second one to be called... SPI1. But SPI1 is the SPI_t struct provided by the I/O headers. The name is taken. So there is no way short of committing mortal sins like undefining things that were defined in the headers to make an SPI library with more than 1 SPI instance that is compatible with existing libraries. But when the hell was the last time you needed two simultaneous SPI ports? And you can still manually do the second one.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Design Decision This cannot be addressed without making a difficult design decision.
Projects
None yet
Development

No branches or pull requests

2 participants