Skip to content

Commit 2fbb6bb

Browse files
committed
Fix 0x00 transmit issue, details see comment
The last commit used the SBI instruction to toggle the TX output pin. If no toggling is required, this instruction was skipped. Executing SBI takes 2 cycles, but skipping only 1 cycle; after 9 consecutive zeros the error was large enough to cause errors on the receiver. The new code uses the out instruction instead, it always executes in 1 cycle. The flash requirements are identical
1 parent efce6fd commit 2fbb6bb

File tree

4 files changed

+45
-27
lines changed

4 files changed

+45
-27
lines changed

main.c

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@ int main(void)
2323

2424
_delay_us(40);
2525
// toggle pattern test: after every bit delay the TX pin is toggled
26-
tinyuart_send_uint8(0b01010101);
27-
_delay_us(10);
26+
// tinyuart_send_uint8(0b01010101);
27+
// _delay_us(10);
2828

2929
// every character test: verify that your receiver can read all chars at the chosen baud rate
3030
// cheap UART-USB converts often have an issue with 0x00
@@ -34,5 +34,9 @@ int main(void)
3434
_delay_us(10);
3535
}
3636

37-
while(1);
37+
while(1)
38+
{
39+
tinyuart_send_uint8(0);
40+
_delay_us(1000);
41+
}
3842
}

tinyuart.cproj

Lines changed: 30 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -43,31 +43,46 @@
4343
</DebugFile>
4444
</AAFDebugFiles>
4545
</AAFDebugger>
46-
<avrtool>com.atmel.avrdbg.tool.simulator</avrtool>
47-
<avrtoolserialnumber />
46+
<avrtool>com.atmel.avrdbg.tool.avrdragon</avrtool>
47+
<avrtoolserialnumber>00A200050668</avrtoolserialnumber>
4848
<avrdeviceexpectedsignature>0x1E9007</avrdeviceexpectedsignature>
4949
<com_atmel_avrdbg_tool_simulator>
50-
<ToolOptions xmlns="">
50+
<ToolOptions>
5151
<InterfaceProperties>
5252
</InterfaceProperties>
53+
<InterfaceName>
54+
</InterfaceName>
5355
</ToolOptions>
54-
<ToolType xmlns="">com.atmel.avrdbg.tool.simulator</ToolType>
55-
<ToolNumber xmlns="">
56+
<ToolType>com.atmel.avrdbg.tool.simulator</ToolType>
57+
<ToolNumber>
5658
</ToolNumber>
57-
<ToolName xmlns="">Simulator</ToolName>
59+
<ToolName>Simulator</ToolName>
5860
</com_atmel_avrdbg_tool_simulator>
5961
<AsfFrameworkConfig>
6062
<framework-data xmlns="">
61-
<options />
62-
<configurations />
63-
<files />
64-
<documentation help="" />
65-
<offline-documentation help="" />
66-
<dependencies>
67-
<content-extension eid="atmel.asf" uuidref="Atmel.ASF" version="3.47.0" />
68-
</dependencies>
69-
</framework-data>
63+
<options />
64+
<configurations />
65+
<files />
66+
<documentation help="" />
67+
<offline-documentation help="" />
68+
<dependencies>
69+
<content-extension eid="atmel.asf" uuidref="Atmel.ASF" version="3.47.0" />
70+
</dependencies>
71+
</framework-data>
7072
</AsfFrameworkConfig>
73+
<avrtoolinterface>ISP</avrtoolinterface>
74+
<com_atmel_avrdbg_tool_avrdragon>
75+
<ToolOptions>
76+
<InterfaceProperties>
77+
<IspClock>125000</IspClock>
78+
</InterfaceProperties>
79+
<InterfaceName>ISP</InterfaceName>
80+
</ToolOptions>
81+
<ToolType>com.atmel.avrdbg.tool.avrdragon</ToolType>
82+
<ToolNumber>00A200050668</ToolNumber>
83+
<ToolName>AVR Dragon</ToolName>
84+
</com_atmel_avrdbg_tool_avrdragon>
85+
<avrtoolinterfaceclock>125000</avrtoolinterfaceclock>
7186
</PropertyGroup>
7287
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
7388
<ToolchainSettings>

tinyuart/tinyuart.c

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
#define CYCLES_LOOP 3
1616

1717
// min cycles per tx bit
18-
#define CYCLES_TX 10
18+
#define CYCLES_TX 9
1919

2020

2121
// the c preprocessor does not support floating point. to get a higher accuracy for divisions the
@@ -28,13 +28,13 @@
2828
// minimum allowed loop value is 1; value 0 is interpreted as 256
2929
#ifdef TINYUART_OPT_HIGH_ACCURACY
3030
// round to nearest cycle
31-
#define CYCLES (((UPSCALE*TINYUART_F_CPU/TINYUART_BAUD-UPSCALE*CYCLES_TX)+UPSCALE/2)/UPSCALE)
31+
#define CYCLES (((UPSCALE*(TINYUART_F_CPU)/(TINYUART_BAUD)-UPSCALE*CYCLES_TX)+UPSCALE/2)/UPSCALE)
3232
#define LOOP_DELAY (CYCLES/CYCLES_LOOP)
3333
#define CYCLES_EXTRA (CYCLES-(LOOP_DELAY*CYCLES_LOOP))
3434

3535
#else
3636
// round to nearest 3 cycles
37-
#define LOOP_DELAY ((((UPSCALE*TINYUART_F_CPU/TINYUART_BAUD-UPSCALE*CYCLES_TX)/CYCLES_LOOP)+UPSCALE/2)/UPSCALE)
37+
#define LOOP_DELAY ((((UPSCALE*(TINYUART_F_CPU)/(TINYUART_BAUD)-UPSCALE*CYCLES_TX)/CYCLES_LOOP)+UPSCALE/2)/UPSCALE)
3838
#define CYCLES_EXTRA 0
3939
#endif
4040

@@ -53,7 +53,7 @@
5353

5454

5555
// Calculate tolerance
56-
#define TOLERANCE_PPM (1000000*TINYUART_BAUD*(LOOP_DELAY*CYCLES_LOOP+CYCLES_TX+CYCLES_EXTRA)/TINYUART_F_CPU-1000000)
56+
#define TOLERANCE_PPM (1000000*(TINYUART_BAUD)*(LOOP_DELAY*CYCLES_LOOP+CYCLES_TX+CYCLES_EXTRA)/TINYUART_F_CPU-1000000)
5757
#define IS_WITHIN_RANGE(x, range) ((x < -range) || (x > range))
5858

5959
#if defined(TINYUART_OPT_TOLERANCE_ERR) && IS_WITHIN_RANGE(TOLERANCE_PPM, 45000)
@@ -104,7 +104,7 @@ void tinyuart_send_uint8(uint8_t data)
104104
(
105105
"mov %[cnt], %[data] \n\t" // use cnt as scratch pad
106106

107-
"sbi %[pin], %[io] \n\t" // Setup START bit => moved for cycles bevore delay loop for accurate timing
107+
"out %[pin], %[mask] \n\t" // Setup START bit => moved for cycles bevore delay loop for accurate timing
108108

109109
"subi %[cnt], 128 \n\t" // invert MSB
110110
"lsl %[cnt] \n\t" // shift to a) generate pattern with XOR b) place msb in carry
@@ -125,8 +125,8 @@ void tinyuart_send_uint8(uint8_t data)
125125
"dec __tmp_reg__ \n\t"
126126
"brne send_bit_delay \n\t"
127127

128-
"sbrc %[data], 0 \n\t" // toggle TX if change is required
129-
"sbi %[pin], %[io] \n\t"
128+
"sbrc %[data], 0 \n\t" // toggle TX if change is required
129+
"out %[pin], %[mask] \n\t"
130130

131131
"ror %[data] \n\t" // rotation to access the 9th bit in carry
132132
"dec %[cnt] \n\t"
@@ -139,7 +139,6 @@ void tinyuart_send_uint8(uint8_t data)
139139
// input values; never write to any of the below
140140
: [mask] "r"(mask), // let compiler put mask in register
141141
[loops] "r"((uint8_t)(LOOP_DELAY+1)), // the 0th loop iteration already decrements, +1 as compensation
142-
[io] "I"(TINYUART_IO_TX),
143142
[pin] "I"(_SFR_IO_ADDR(TINYUART_PIN))
144143

145144
// cobblers: registers modified without compiler already knowing

tinyuart/tinyuart.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
#define TINYUART_F_CPU 9600000
2222

2323
// select a baud rate
24-
#define TINYUART_BAUD 960000
24+
#define TINYUART_BAUD 500000
2525

2626
// specify pins used
2727
#define TINYUART_PORT PORTB

0 commit comments

Comments
 (0)