Using an ATTiny13a running at 9.6Mhz and BasicSerial for serial communication, 115200 baud works well.
Microcore is used as core, USBasp as programmer, Arduino IDE 1.8.5.
Internal oscillator selected.
However changing the speed to 4.8Mhz resulted in garbage on the reciver/Serial Monitor.
The 4.8Mhz speed calibration is default done using the same value as the 9.6Mhz even though the ATTiny13a has a calibration byte for each of the two speeds.
I have searched and not found a simple way to calibrate the 4.8Mhz oscillator in order to use the serial communication.
As a concequence, here is my simple sketch using the serial output to the Arduino IDE Serial Monitor or a terminal emulator.
You can read the two calibration bytes using the avrdude as explained in the code or a value around 0x40 as starting point.
The sketch first increments the OSCCAL value, then decrement it in a loop.
The value is output via the serial communication. Mostly the output does not make sense, but once the serial speed is close to the nominal speed, you can read the values shown: OSCCAL = xx where xx is a hex number.
I found that the best result was to use a value in the top half of the shown values.
You can either store the value in EEPROM or load it into OSCCAL at the start of the sketch.
Note that the result might change depending on VCC, 3.3 or 5v.
The sketch can be used for either 4.8Mhz or 9.6Mhz internal oscillator.
/**
Find OSCCAL value for tuning the internal ATtiny13a oscillator
Sends the value of OSCCAL to serial console.
Mostly it appears as gibberish, but once the frequency is about right, readable output appears.
Note the max and min readable containing OSCCAL = xx.
5v VCC values are most likely different from 3v/3.3v VCC, but some values should be included in both cases.
*/
#include <BasicSerial.h> //Pin 5 = tx, 115200 Baud
//From avrdude read: avrdude -p t13 -c usbasp -U calibration:r:calibration.txt:h
//calibration.txt contains 0x33,0x4c which are the 9.6Mhz and 4.8Mhz calibration values
//NOTE: Change values below as read from the individual attiny13a
#if F_CPU == 9600000
const byte oscorg = 0x33;
#elif F_CPU == 4800000
const byte oscorg = 0x4c;
#endif
//Limits for testing osccal value
const byte oschigh = 0x60; //Adjust as neccessary, max 0x7f, seven bits
const byte osclow = 0x20; //Adjust as neccessary, min 0
void serOut( const char* str)
{
while (*str) TxByte (*str++);
}
//Thanks to
//Murray Horn.
//https://www.avrfreaks.net/forum/converting-int-hex-number
void sendhex( uint8_t nibble) {
if ( nibble > 9 )
nibble += ('A' - '0' - 10);
TxByte(nibble += '0');
}
uint8_t sendhexbyte(uint8_t value) {
sendhex((value & 0xF0) >> 4);
sendhex((value & 0x0F));
}
int main (void)
{
byte oscval = oscorg;
bool bUp = true;
sendhexbyte(OSCCAL); //Send original value, probably unreadable.
OSCCAL = oscval; //Set start value
while (1) {
if (bUp) {
oscval++;
if (oscval > oschigh ) {
oscval = oscorg - 1;
bUp = false;
}
} else {
oscval--;
if (oscval < osclow ) {
oscval +=2;
bUp = true;
}
}
serOut("OSCCAL = ");
sendhexbyte(OSCCAL);
TxByte('\n');
//Set new osccal value and do a short wait
OSCCAL = oscval;
#if F_CPU == 9600000
// Generated by delay loop calculator
// at http://www.bretmulvey.com/avrdelay.html
//
// Delay 4 800 000 cycles
// 500ms at 9.6 MHz
asm volatile (
" ldi r18, 25" "\n"
" ldi r19, 90" "\n"
" ldi r20, 178" "\n"
"1: dec r20" "\n"
" brne 1b" "\n"
" dec r19" "\n"
" brne 1b" "\n"
" dec r18" "\n"
" brne 1b" "\n"
" rjmp 1f" "\n"
"1:" "\n"
);
#elif F_CPU == 4800000
// Generated by delay loop calculator
// at http://www.bretmulvey.com/avrdelay.html
//
// Delay 2 400 000 cycles
// 500ms at 4.8 MHz
asm volatile (
" ldi r18, 13" "\n"
" ldi r19, 45" "\n"
" ldi r20, 216" "\n"
"1: dec r20" "\n"
" brne 1b" "\n"
" dec r19" "\n"
" brne 1b" "\n"
" dec r18" "\n"
" brne 1b" "\n"
" rjmp 1f" "\n"
"1:" "\n"
);
#endif
}
}
And the part of the serial output close to the usable values looks like:
⸮P⸮NZH⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮= 4A
OSCCAL = 49
OSCCAL = 48
OSCCAL = 47
OSCCAL = 46
OSCCAL = 45
OSCCAL = 44
OSCCAL = 43
OSCCAL = 42
OSCCAL = 41
OSCCAL = 40
OSCCAL = 3F
OSCCAL = 3E
OSCCAL = 3D
OSCCAL = 3C
⸮⸮C⸮⸮⸮ = 3⸮
The log contains characters which cannot be included here, hence only this small example.