#include <xc.h>
|
|
#include <avr/io.h>
|
|
|
|
//this req'd for (and before calling) delay
|
|
//see delay.h
|
|
//compiler optimizations must also be enabled
|
|
#define F_CPU 8000000
|
|
#include <util/delay.h>
|
|
|
|
#include <avr/interrupt.h>
|
|
//#include <avr/sleep.h>
|
|
//#include <util/atomic.h>
|
|
//#include <avr/wdt.h>
|
|
|
|
|
|
|
|
|
|
|
|
//tests5 tested and works (at ~950hz). unplug cable to programmer to see pin 4 active.
|
|
//however...
|
|
//tests6 DEADEND
|
|
//never worked right. giving up and using delay.
|
|
|
|
//reference: https://www.avrfreaks.net/forum/sample-project-attiny10
|
|
//https://blog.podkalicki.com/attiny13-blinky-with-timer-compa/
|
|
//watchdog is too slow and inaccurate to get 6000Hz
|
|
|
|
//ISR(TIM0_COMPA_vect)
|
|
//{
|
|
// // Toggle PB2 Hi/Low depending on current state
|
|
// PINB = 1<<2;
|
|
// TIFR0 |= 1<<OCF0A; //clear flag (is this required here? documentation unclear)
|
|
// //PORTB ^= _BV(LED_PIN); // toggle LED pin
|
|
//}
|
|
|
|
|
|
/*
|
|
Delay in powerdown mode. Wake up by watchdog interrupt.
|
|
* //NOTE: see earlier code, e.g. tests3 in attiny10 elec projects 2020
|
|
*/
|
|
/*
|
|
void delay_power_down_wdt(uint8_t wdto)
|
|
{
|
|
wdt_reset();
|
|
wdt_enable(wdto);
|
|
WDTCSR |= (1<<WDIE);
|
|
//so far (with 128Khz clk) this sleep will be about 30-40 seconds.
|
|
|
|
//(however, I'll add the below to)
|
|
//adjust sleep speed here:
|
|
|
|
// 0110 is 1hz at 128KHz
|
|
//WDTCSR |= (0<< WDP3);
|
|
//WDTCSR |= (1<< WDP2);
|
|
//WDTCSR |= (1<< WDP1);
|
|
//WDTCSR |= (0<< WDP0);
|
|
|
|
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
|
|
sleep_enable();
|
|
// Make sure interrups are enabled and the I flag is restored
|
|
NONATOMIC_BLOCK(NONATOMIC_RESTORESTATE)
|
|
{
|
|
sleep_cpu();
|
|
wdt_disable();
|
|
}
|
|
sleep_disable();
|
|
}
|
|
*/
|
|
|
|
int main(void)
|
|
{
|
|
|
|
//// //Write CCP (to enable changing clock)
|
|
CCP = 0xD8;
|
|
//// //change CLK to 128KHz
|
|
// CLKMSR = 0b01;
|
|
//change clk to 8mhz
|
|
CLKMSR = 0b00;
|
|
|
|
//clock prescaler from divide by 8 (defualt) to none
|
|
|
|
//CLKPS0 = 0x0;
|
|
//CLKPS1 = 0x0;
|
|
//Just omit the bits that are reserved, see also clkmsr which is 2 bit active
|
|
// 8 bit inactive
|
|
CLKPSR = 0b0000;
|
|
|
|
//notes: test results (osccal is 8 bit)
|
|
// osccal | hz output
|
|
// 0xe6 10khz
|
|
// 0x06 3.58khz
|
|
// 0x0F 3.83Khz
|
|
// 0x2F 4.62Khz
|
|
// 0x5F 5.84Khz
|
|
// 0x65 6.003KHz -winrar (for this chip))
|
|
// 0x8F 7.27Khz
|
|
OSCCAL = 0x65;
|
|
|
|
//////// OCR0A = 0;
|
|
//////// TCNT0 = 0;
|
|
//////// TCCR0A = 0;
|
|
//////// TCCR0B = 0;
|
|
////////
|
|
//////// TCCR0A |= _BV(WGM01); // set timer counter mode to CTC
|
|
//////// // TCCR0B |= _BV(CS02)|_BV(CS00); // set prescaler to 1024 (CLK=1200000Hz/1024/256=4.57Hz, 0.22s)
|
|
//////// TCCR0B |= _BV(CS00); // set prescaler to 1 (CLK=1MHz/1)
|
|
//OCR0A is 16 bits. in ASM it must be loaded separately.
|
|
//in C, it can be loaded > 256? (test)
|
|
|
|
//520 about 950hz, 25us wide pulse
|
|
//OCR0A = 520; // with one timer, ever 166.667hz we want to count once (3000hz)
|
|
|
|
//OCR0A = 1; //475hz
|
|
|
|
//this goes to 475hz (pulses). doesn't make sense.
|
|
//// OCR0AH = 0xFF; //
|
|
//// OCR0AL = 0xFF;
|
|
|
|
//attiny10 output compare broken apparently
|
|
//this still 960hz, with 100us or so pulse size (high is 100us, low is longer)
|
|
//OCR0A = 100;
|
|
|
|
|
|
//inline asm to load values into 16 bit register
|
|
|
|
//; variables
|
|
//; For 1 Hz output, the timer delay has to be 1/2 second (1/2 second on / 1/2 second off)
|
|
//; delay = OCR0A * 1024 * 8 / 8000000
|
|
//; for 1/2 second, OCR0A = 488 (0x01E8)
|
|
//.EQU OCR0AHigh = 0x01
|
|
//.EQU OCR0ALow = 0xe8
|
|
// in bash type: printf "%x\n" 488
|
|
//.EQU OCR0AHigh = 0x02
|
|
//.EQU OCR0ALow = 0x08
|
|
|
|
// ldi r17, OCR0AHigh //; Sets the output compare register value
|
|
//ldi r16, OCR0ALow
|
|
|
|
//this asm doesn't work (why?) //perhaps OCR0A is really just 8 bits on attiny10...?)
|
|
////// asm volatile(
|
|
////// "ldi r17, 0x02"
|
|
////// "ldi r16, 0x08"
|
|
////// "out OCR0AH, r17"
|
|
////// "out OCR0AL, r16"
|
|
////// );
|
|
|
|
//this asm works
|
|
// asm volatile("nop\n\t"
|
|
//"nop\n\t"
|
|
//"nop\n\t"
|
|
//"nop\n\t"
|
|
//::);
|
|
////////
|
|
//////// TIMSK0 |= _BV(OCIE0A); // enable Timer CTC interrupt
|
|
////////
|
|
// PB2 change to output
|
|
DDRB = 1<<2;
|
|
//// sei();
|
|
|
|
|
|
int x = 0;
|
|
while(1)
|
|
{
|
|
|
|
//this goes about 60.3KHz.
|
|
//experiment FAIL
|
|
//will just buy a 6KHz oscillator.
|
|
|
|
PINB = 1<<2;
|
|
//EDIT: disabled optimization in mplab (level 0)
|
|
//and ended up geting much slower IO
|
|
//asm("nop;");
|
|
//for(x=0;x<10;x++){
|
|
|
|
//note it's _delay_us not delay_us
|
|
|
|
//delay_us(1) is 44.3KHz
|
|
//_delay_us(8); //9 is 6.4KHz, 8 is roughly 7.2KHz
|
|
//delay_us(10) is 5.8KHz
|
|
//not much granularity there...)
|
|
//so adding the following...
|
|
if( x == 3){
|
|
_delay_us(4);//these two are 5.98 or so KHz
|
|
x = 0;
|
|
goto jump;
|
|
}
|
|
|
|
//NOTE: the above ends up causing an ugly looking clock. may not matter
|
|
//for fpga clocking off of rising edge, BUT, it is ugly, should remove,
|
|
//and just do single delay. Will do in part 9.
|
|
|
|
x++;
|
|
jump:
|
|
//in combination with the jump, gives closer to 6KHz
|
|
_delay_us(8);
|
|
|
|
|
|
|
|
///below didn't work out, so using osccal
|
|
//bit convuluted anyways
|
|
/*if( x == 4){
|
|
_delay_us(1);
|
|
//x = 0;
|
|
goto jump;
|
|
}
|
|
if( x == 8){
|
|
_delay_us(2);
|
|
x = 0;
|
|
goto jump;
|
|
}
|
|
x++;
|
|
jump:
|
|
//in combination with the jump, gives closer to 6KHz
|
|
_delay_us(8);*/
|
|
|
|
|
|
//the above idles at 5.98 - 5.99KHz.
|
|
//best so far.
|
|
//Now, calibrate oscillator with OSCCAL
|
|
|
|
//if more accuracy desired.
|
|
//or adjust if clause above
|
|
|
|
//tried to make my own delay in ASM, BUT
|
|
//compiler keeps optimizing it out (even w/out optimization enabled)
|
|
//... some other flag may be culprit. So instead will use delay_us. Two delay
|
|
//functions are delay_ms and delay_us. see headers at top and delay.h)
|
|
/* __asm__("mov r16, r17;"
|
|
"mov r17, r16;"
|
|
"inc r16;"
|
|
"dec r16;"
|
|
"mov r16, r17;"
|
|
"mov r17, r16;"
|
|
"inc r16;"
|
|
"dec r16;"
|
|
"clr r16;"
|
|
"clr r17;"
|
|
"clr r18;"
|
|
"clr r19;"
|
|
"clr r20;"
|
|
"clr r21;"
|
|
"clr r22;"
|
|
"clr r23;"
|
|
"mov r16, r17;"
|
|
"mov r17, r16;"
|
|
"inc r16;"
|
|
"dec r16;"
|
|
"mov r16, r17;"
|
|
"mov r17, r16;"
|
|
"clr r16;"
|
|
"clr r17;"
|
|
"clr r18;"
|
|
"clr r19;"
|
|
"clr r20;"
|
|
"clr r21;"
|
|
"clr r22;"
|
|
"clr r23;"
|
|
"mov r16, r17;"
|
|
"mov r17, r16;"
|
|
"inc r16;"
|
|
"dec r16;"
|
|
"mov r16, r17;"
|
|
"mov r17, r16;"
|
|
|
|
|
|
);*/
|
|
|
|
|
|
|
|
//mplab delay is:
|
|
/** \ingroup util_delay_basic
|
|
|
|
Delay loop using an 8-bit counter \c __count, so up to 256
|
|
iterations are possible. (The value 256 would have to be passed
|
|
as 0.) The loop executes three CPU cycles per iteration, not
|
|
including the overhead the compiler needs to setup the counter
|
|
register.
|
|
|
|
Thus, at a CPU speed of 1 MHz, delays of up to 768 microseconds
|
|
can be achieved.
|
|
*/
|
|
//////////void
|
|
//////////_delay_loop_1(uint8_t __count)
|
|
//////////{
|
|
////////// __asm__ volatile (
|
|
////////// "1: dec %0" "\n\t"
|
|
////////// "brne 1b"
|
|
////////// : "=r" (__count)
|
|
////////// : "0" (__count)
|
|
////////// );
|
|
//////////}
|
|
//////////
|
|
//////////
|
|
//ignore below
|
|
// asm("nop;""nop;""nop;""nop;""nop;"
|
|
//"nop;""nop;"//"nop;""nop;"//"nop;""nop;"
|
|
//);
|
|
//}//just this asm block is about 121.22KHz
|
|
|
|
}
|
|
}
|
|
|