<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en-gb">
	<link rel="self" type="application/atom+xml" href="https://forums.obdev.at/app.php/feed/topic/6280" />

	<title>Objective Development Forums</title>
	
	<link href="https://forums.obdev.at/index.php" />
	<updated>2011-12-15T00:58:24+02:00</updated>

	<author><name><![CDATA[Objective Development Forums]]></name></author>
	<id>https://forums.obdev.at/app.php/feed/topic/6280</id>

		<entry>
		<author><name><![CDATA[Peter Chaffe]]></name></author>
		<updated>2011-12-15T00:58:24+02:00</updated>

		<published>2011-12-15T00:58:24+02:00</published>
		<id>https://forums.obdev.at/viewtopic.php?t=6280&amp;p=20445#p20445</id>
		<link href="https://forums.obdev.at/viewtopic.php?t=6280&amp;p=20445#p20445"/>
		<title type="html"><![CDATA[Re: Running Attiny45 on xtal]]></title>

		
		<content type="html" xml:base="https://forums.obdev.at/viewtopic.php?t=6280&amp;p=20445#p20445"><![CDATA[
For anyone interested here is a skimmed down version meant for use with a Crystal:<br /><div class="codebox"><p>Code: </p><pre><code>#include &lt;avr/io.h&gt;<br />#include &lt;avr/wdt.h&gt;<br />#include &lt;avr/eeprom.h&gt;<br />#include &lt;avr/interrupt.h&gt;<br />#include &lt;avr/pgmspace.h&gt;<br />#include &lt;util/delay.h&gt;<br />#include &lt;stdlib.h&gt;<br /><br />#include &quot;usbdrv.h&quot;<br />#include &quot;oddebug.h&quot;<br /><br />/* ------------------------------------------------------------------------- */<br /><br />static uchar    reportBuffer&#91;2&#93;;    /* buffer for HID reports */<br />static uchar    idleRate;           /* in 4 ms units */<br />static uchar    reportCount;      /* current report */<br />static unsigned int   TimerDelay;      /* counter for delay period */<br /><br />/* ------------------------------------------------------------------------- */<br /><br />PROGMEM char usbHidReportDescriptor&#91;USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH&#93; = { /* USB report descriptor */<br />    0x05, 0x01,                    // USAGE_PAGE (Generic Desktop)<br />    0x09, 0x06,                    // USAGE (Keyboard)<br />    0xa1, 0x01,                    // COLLECTION (Application)<br />    0x05, 0x07,                    //   USAGE_PAGE (Keyboard)<br />    0x19, 0xe0,                    //   USAGE_MINIMUM (Keyboard LeftControl)<br />    0x29, 0xe7,                    //   USAGE_MAXIMUM (Keyboard Right GUI)<br />    0x15, 0x00,                    //   LOGICAL_MINIMUM (0)<br />    0x25, 0x01,                    //   LOGICAL_MAXIMUM (1)<br />    0x75, 0x01,                    //   REPORT_SIZE (1)<br />    0x95, 0x08,                    //   REPORT_COUNT (8)<br />    0x81, 0x02,                    //   INPUT (Data,Var,Abs)<br />    0x95, 0x01,                    //   REPORT_COUNT (1)<br />    0x75, 0x08,                    //   REPORT_SIZE (8)<br />    0x25, 0x65,                    //   LOGICAL_MAXIMUM (101)<br />    0x19, 0x00,                    //   USAGE_MINIMUM (Reserved (no event indicated))<br />    0x29, 0x65,                    //   USAGE_MAXIMUM (Keyboard Application)<br />    0x81, 0x00,                    //   INPUT (Data,Ary,Abs)<br />    0xc0                           // END_COLLECTION<br />};<br /><br />static void buildReport(void)<br />{<br />uchar   key = 0;<br /><br /><br />    if(reportCount == 0){<br />        key = 0x39;<br />    }<br /><br />   reportCount++;<br />    reportBuffer&#91;0&#93; = 0;    /* no modifiers */<br />    reportBuffer&#91;1&#93; = key;<br />}<br /><br />static void timerPoll(void)<br />{<br />   static unsigned int timerCnt;<br /><br />    if(TIFR &amp; (1 &lt;&lt; TOV1)){<br />        TIFR = (1 &lt;&lt; TOV1); /* clear overflow */<br />        if(++timerCnt &gt;= TimerDelay){       /* check for end of pseudorandom delay */<br />            <br />         TimerDelay = 2835 + rand();      /* 1/63s * 63 * 30 + 0...32767 */<br />         timerCnt = 0;<br />         reportCount = 0; /* start report */<br />        }<br />    }<br />}<br /><br />/* ------------------------------------------------------------------------- */<br /><br />static void timerInit(void)<br />{<br />    TCCR1 = 0x0b;           /* select clock: 16.5M/1k -&gt; overflow rate = 16.5M/256k = 62.94 Hz */<br />}<br /><br /><br />/* ------------------------------------------------------------------------- */<br />/* ------------------------ interface to USB driver ------------------------ */<br />/* ------------------------------------------------------------------------- */<br /><br />uchar   usbFunctionSetup(uchar data&#91;8&#93;)<br />{<br />usbRequest_t    *rq = (void *)data;<br /><br />    usbMsgPtr = reportBuffer;<br />    if((rq-&gt;bmRequestType &amp; USBRQ_TYPE_MASK) == USBRQ_TYPE_CLASS){    /* class request type */<br />        if(rq-&gt;bRequest == USBRQ_HID_GET_REPORT){  /* wValue: ReportType (highbyte), ReportID (lowbyte) */<br />            /* we only have one report type, so don't look at wValue */<br />            buildReport();<br />            return sizeof(reportBuffer);<br />        }else if(rq-&gt;bRequest == USBRQ_HID_GET_IDLE){<br />            usbMsgPtr = &amp;idleRate;<br />            return 1;<br />        }else if(rq-&gt;bRequest == USBRQ_HID_SET_IDLE){<br />            idleRate = rq-&gt;wValue.bytes&#91;1&#93;;<br />        }<br />    }else{<br />        /* no vendor specific requests implemented */<br />    }<br />   return 0;<br />}<br /><br />/* ------------------------------------------------------------------------- */<br />/* --------------------------------- main ---------------------------------- */<br />/* ------------------------------------------------------------------------- */<br /><br />int main(void)<br />{<br />uchar   i;<br /><br />    odDebugInit();<br />    usbDeviceDisconnect();<br />    for(i=0;i&lt;20;i++){  /* 300 ms disconnect */<br />        _delay_ms(15);<br />    }<br />    usbDeviceConnect();<br /><br />    wdt_enable(WDTO_1S);<br />    timerInit();<br />   TimerDelay = 630; /* initial 10 second delay */<br /><br />    usbInit();<br />    sei();<br />    for(;;){    /* main event loop */<br />        wdt_reset();<br />        usbPoll();<br /><br />      /* A USB keypress cycle is defined as a scancode being present in a report, and<br />      then absent from a later report. To press and release the Caps Lock key, instead of<br />      holding it down, we need to send the report with the Caps Lock scancode and<br />      then an empty report. */<br /><br />        if(usbInterruptIsReady() &amp;&amp; reportCount &lt; 2){ /* we can send another key */<br />            buildReport();<br />            usbSetInterrupt(reportBuffer, sizeof(reportBuffer));<br />           }<br />        timerPoll();<br />    }<br />    return 0;<br />}<br /></code></pre></div><p>Statistics: Posted by <a href="https://forums.obdev.at/memberlist.php?mode=viewprofile&amp;u=6086">Peter Chaffe</a> — Thu Dec 15, 2011 12:58 am</p><hr />
]]></content>
	</entry>
		<entry>
		<author><name><![CDATA[Peter Chaffe]]></name></author>
		<updated>2011-12-13T22:59:12+02:00</updated>

		<published>2011-12-13T22:59:12+02:00</published>
		<id>https://forums.obdev.at/viewtopic.php?t=6280&amp;p=20436#p20436</id>
		<link href="https://forums.obdev.at/viewtopic.php?t=6280&amp;p=20436#p20436"/>
		<title type="html"><![CDATA[Running Attiny45 on xtal]]></title>

		
		<content type="html" xml:base="https://forums.obdev.at/viewtopic.php?t=6280&amp;p=20436#p20436"><![CDATA[
Hi, Trying to understand the code better. I'm using the tiny45 for the caps locker circuit (very similar to the easy logger).<br /><br />Got it running ok using the internal osc at 16500000 so now want to try using an xtal instead.<br />Changed the fuses low 0xff &amp; high 0xdf, and used a 12000000 crystal, the circuit works fine still...<br /><br />a quick explanation of this line would be helpful:<div class="codebox"><p>Code: </p><pre><code>    TCCR1 = 0x0b;           /* select clock: 16.5M/1k -&gt; overflow rate = 16.5M/256k = 62.94 Hz */</code></pre></div><br /><br /><br />What I would now like to know now is with the crystal fiited and running ok, what parts of this c code is now redundant?<br />the more i delete, the more errors im getting! Thought that most of this code was for the PLL which I thought guess shouldn't be needed now...<br /><div class="codebox"><p>Code: </p><pre><code>static void timerInit(void)<br />{<br />    TCCR1 = 0x0b;           /* select clock: 16.5M/1k -&gt; overflow rate = 16.5M/256k = 62.94 Hz */<br />}<br /><br />/* ------------------------ interface to USB driver ------------------------ */<br /><br />uchar   usbFunctionSetup(uchar data&#91;8&#93;)<br />{<br />usbRequest_t    *rq = (void *)data;<br /><br />    usbMsgPtr = reportBuffer;<br />    if((rq-&gt;bmRequestType &amp; USBRQ_TYPE_MASK) == USBRQ_TYPE_CLASS){    /* class request type */<br />        if(rq-&gt;bRequest == USBRQ_HID_GET_REPORT){  /* wValue: ReportType (highbyte), ReportID (lowbyte) */<br />            /* we only have one report type, so don't look at wValue */<br />            buildReport();<br />            return sizeof(reportBuffer);<br />        }else if(rq-&gt;bRequest == USBRQ_HID_GET_IDLE){<br />            usbMsgPtr = &amp;idleRate;<br />            return 1;<br />        }else if(rq-&gt;bRequest == USBRQ_HID_SET_IDLE){<br />            idleRate = rq-&gt;wValue.bytes&#91;1&#93;;<br />        }<br />    }else{<br />        /* no vendor specific requests implemented */<br />    }<br />   return 0;<br />}<br /><br />/* ------------------------ Oscillator Calibration ------------------------- */<br /><br />/* Calibrate the RC oscillator to 8.25 MHz. The core clock of 16.5 MHz is<br /> * derived from the 66 MHz peripheral clock by dividing. Our timing reference<br /> * is the Start Of Frame signal (a single SE0 bit) available immediately after<br /> * a USB RESET. We first do a binary search for the OSCCAL value and then<br /> * optimize this value with a neighboorhod search.<br /> * This algorithm may also be used to calibrate the RC oscillator directly to<br /> * 12 MHz (no PLL involved, can therefore be used on almost ALL AVRs), but this<br /> * is wide outside the spec for the OSCCAL value and the required precision for<br /> * the 12 MHz clock! Use the RC oscillator calibrated to 12 MHz for<br /> * experimental purposes only!<br /> */<br />static void calibrateOscillator(void)<br />{<br />uchar       step = 128;<br />uchar       trialValue = 0, optimumValue;<br />int         x, optimumDev, targetValue = (unsigned)(1499 * (double)F_CPU / 10.5e6 + 0.5);<br /><br />    /* do a binary search: */<br />    do{<br />        OSCCAL = trialValue + step;<br />        x = usbMeasureFrameLength();    /* proportional to current real frequency */<br />        if(x &lt; targetValue)             /* frequency still too low */<br />            trialValue += step;<br />        step &gt;&gt;= 1;<br />    }while(step &gt; 0);<br />    /* We have a precision of +/- 1 for optimum OSCCAL here */<br />    /* now do a neighborhood search for optimum value */<br />    optimumValue = trialValue;<br />    optimumDev = x; /* this is certainly far away from optimum */<br />    for(OSCCAL = trialValue - 1; OSCCAL &lt;= trialValue + 1; OSCCAL++){<br />        x = usbMeasureFrameLength() - targetValue;<br />        if(x &lt; 0)<br />            x = -x;<br />        if(x &lt; optimumDev){<br />            optimumDev = x;<br />            optimumValue = OSCCAL;<br />        }<br />    }<br />    OSCCAL = optimumValue;<br />}<br />/*<br />Note: This calibration algorithm may try OSCCAL values of up to 192 even if<br />the optimum value is far below 192. It may therefore exceed the allowed clock<br />frequency of the CPU in low voltage designs!<br />You may replace this search algorithm with any other algorithm you like if<br />you have additional constraints such as a maximum CPU clock.<br />For version 5.x RC oscillators (those with a split range of 2x128 steps, e.g.<br />ATTiny25, ATTiny45, ATTiny85), it may be useful to search for the optimum in<br />both regions.<br />*/<br /><br />void    usbEventResetReady(void)<br />{<br />    calibrateOscillator();<br />    eeprom_write_byte(0, OSCCAL);   /* store the calibrated value in EEPROM */<br />}<br /><br />/* ------------------------------------------------------------------------- */<br />/* --------------------------------- main ---------------------------------- */<br />/* ------------------------------------------------------------------------- */<br /><br />int main(void)<br />{<br />uchar   i;<br />uchar   calibrationValue;<br /><br />    calibrationValue = eeprom_read_byte(0); /* calibration value from last time */<br />    if(calibrationValue != 0xff){<br />        OSCCAL = calibrationValue;<br />    }<br />    odDebugInit();<br />    usbDeviceDisconnect();<br />    for(i=0;i&lt;20;i++){  /* 300 ms disconnect */<br />        _delay_ms(15);<br />    }<br />    usbDeviceConnect();<br /><br />    wdt_enable(WDTO_1S);<br />    timerInit();<br />   TimerDelay = 630; /* initial 10 second delay */<br /><br />    usbInit();<br />    sei();<br />    for(;;){    /* main event loop */<br />        wdt_reset();<br />        usbPoll();<br /><br />      /* A USB keypress cycle is defined as a scancode being present in a report, and<br />      then absent from a later report. To press and release the Caps Lock key, instead of<br />      holding it down, we need to send the report with the Caps Lock scancode and<br />      then an empty report. */<br /><br />        if(usbInterruptIsReady() &amp;&amp; reportCount &lt; 2){ /* we can send another key */<br />            buildReport();<br />            usbSetInterrupt(reportBuffer, sizeof(reportBuffer));<br />           }<br />        timerPoll();<br />    }<br />    return 0;<br />}<br /></code></pre></div><br /><br />Appreciate any guidance...<p>Statistics: Posted by <a href="https://forums.obdev.at/memberlist.php?mode=viewprofile&amp;u=6086">Peter Chaffe</a> — Tue Dec 13, 2011 10:59 pm</p><hr />
]]></content>
	</entry>
	</feed>
