How does 'Serial.print(0x41);' method ultimately bring 65 on Serial Monitor?

1. To see 6 (an image) on Serial Monitor, the ASCII code 0x36 must be arriving at the Serial Monitor.

2. To see 5 (an image) on Serial Monitor, the ASCII code 0x35 must be arriving at the Serial Monitor.

3. In view of the above two facts, is it technically correct to say that the argument 0x41 of the Serial.print(0x41) method is transformed to digit-6 (000001010) and digit-5 (00000101) of its decimal equivalent 65 by virtue of 'default base 10' which is assumed to be present as the 2nd argument of the .print() method when the 1st argument is a number?

@J-M-L has answered in the negative in this post and then he has elaborately explained the 'actual mechanism' in the light of 'source codes' in an elegant style, which has been closely observed by @larryd who has proposed that the works of @J-M-L could be reworked and presented in this 'General Discussion Section' ('Tutorial Section').

It is hoped that this thread would receive scholastic contributions from @J-M-L and others in popular styles.

... to be continued

The usual enumerated pseudo-scientific trivialities.

GolamMostafa:
... to be continued

Please do not.

Whandall:
Please do not.

As @larryd has proposed for a tutorial (discussion), let the thread be continued. Hopefully, this will bring an opportunity for the interested forum members to digest all those presented by @J-M-L in this post.

It is my strong intuitive feeling that the whole process of: Serial.print(0x41) --------> 65 in Serial Monitor could be described at conceptual level by the following block diagram.

How to implement the above block diagram so that the ASCII codes 0x36 and 0x35 will successively arrive at the Serial Monitor to show 65? @J-M-L has shown that in this post.

When everything has already been given in the said post of @J-M-L, then do we still need further discussion? @larryd and the Moderator have already expressed -- YES!

No, a moderator moved the thread here, from "Tutorials".

No opinion on any further discussion was given, or should be implied.

(And for the record, I don't understand the block diagram)

The topic comes up every now and then on the forums.

Having a tutorial on this for new users to refer to would be a benefit.

AWOL:
No, a moderator moved the thread here, from "Tutorials".

In some cases, a (the) Moderator (there are at least three Moderators of whom particular One is very active and inspiring) deletes post/thread without any notification. This time, a Moderator has removed the thread/post to the Discussion Section -- a process that has appeared to me that (the) Moderator has wished the topics to be continued.

AWOL:
(And for the record, I don't understand the block diagram)


Figure-1: Conceptual level view of how Serial.print(0x41) ultimately brings 65 on Serial Monitor

1. Assume that the ASCII codes 0x36 and 0x35 are 'somehow' created and now they are to be placed onto the UDR0 Register (UART Data Register-0) for onward transmission via TX-pn/TX-Buffer. How do they go over there?

2. What I have understood from this post of @J-M-L are these:
(1) It is the Serial.write() method that puts the data bytes 0x36 and 0x35 into the FIFO Buffer of Fig-1. The transfer time (parallel mode) into FIFO Buffer is faster than the transfer time 'from FIFO Buffer into UDR0 Register (parallel mode) and then from UDR0 Register to TX-pin/TX-Buffer (serial mode)'.

(2) Initially, the UDR0 Register is at ready state to accept a data byte for onward transmission to TX-Pin/TX-Buffer. The MCU transfers the data byte (0x36) from FIFO Buffer to UDR0 Register in parallel fashion; data from UDR0 Register to TX-Pin/TX-Buffer goes in serial fashion.

(3) Once the UDR0 Register has finished transferring the data byte (0x36) into TX-pin/TX-Buffer, an 'Interrupt Request Signal (TXRDY IRQ) (Fig-1)' triggers the MCU. The next data byte (0x35) is written onto UDR0 Register on interrupt basis. The interrupt process goes on until the remaining data bytes (if any) of the FIFO Buffer get transferred into UDR0 Register byte-by-byte.

3. How are the ASCII data bytes (0x36 and 0x35) created?
....... difficult sub-section; not yet fully understood from this post of @J-M-L.

It seems to me all of this is covered in detail in the Atmega 328 datasheet.

...R

Robin2:
It seems to me all of this is covered in detail in the Atmega 328 datasheet.

We don't see the data sheets to discuss Arduino's UART Layers such as RX/TX FIFO Buffers, Serial.write() code, and other high level codes found in this post (taken from this document) of @J-M-L.

GolamMostafa:
We don't see the data sheets to discuss Arduino's UART Layers such as RX/TX FIFO Buffers, Serial.write() code,

True.

All the Arduino code comes with the IDE if you really want to study it. But as it seems to work very reliably why would you need to?

...R

Robin2:
All the Arduino code comes with the IDE if you really want to study it. But as it seems to work very reliably why would you need to?

The Reference, Text, and Hand Books are available in PDF format in the net; yet, many users explore shops for the printed copies of those books. Why?

GolamMostafa:
yet, many users explore shops for the printed copies of those books. Why?

Seems like the perfect opportunity for you to fill a gap in the market by writing and publishing the book they are all looking for.

...R

Robin2:
Seems like the perfect opportunity for you to fill a gap in the market by writing and publishing the book they are all looking for.

GolamMostafa:
3. How are the ASCII data bytes (0x36 and 0x35) created?
....... difficult sub-section; not yet fully understood from this post of @J-M-L.

OK! Help me in the study and and step-by-step analysis of the following subprogram/method which creates the ASCII codes (0x36 and 0x35) for the argument of this command: Serial.print(0x41). The outcomes of this study could be included in the 'to be published book' and also be presented as a tutorial in the Education and Teaching Section. (This method is a part of this document.)

size_t Print::printNumber(unsigned long n, uint8_t base)
{
  char buf[8 * sizeof(long) + 1]; // Assumes 8-bit chars plus zero byte.
  char *str = &buf[sizeof(buf) - 1];

  *str = '\0';

  // prevent crash if called with base == 1
  if (base < 2) base = 10;

  do {
    char c = n % base;
    n /= base;

    *--str = c < 10 ? c + '0' : c + 'A' - 10;
  } while(n);

  return write(str);
}

What is there to analyse?
This isn't Eng. Lit.

AWOL:
What is there to analyse?
This isn't Eng. Lit.

We receive, analyse, synthesize, conclude, and then present.

The method, printNumber(), receives an unsigned 32-bit number (0x00000000 - 0xFFFFFFFF = 0 - 4294967295). So, an array of 16-byte wide is enough to hold the ASCII codes for the digits of the decimal number; instead, the method has declared an array of 32-byte wide (char buf[8*4]). Why? Do we need to do some kind of analysis to get answer in favor of 32-byte declaration?

GolamMostafa:
Why? Do we need to do some kind of analysis to get answer in favor of 32-byte declaration?

I hope that is rhetorical, but in case it isn't, consider the "base" parameter.

One of those threads where things are made more complicated because the world needs more 'complicated things' !

Don't over-think simple concepts!