/* "avrstick USBdisk example" */
/* */
/* This demo implements an USB */
/* virtual COM port and an USB */
/* MassStorage device. */
/* (without virtual filesystem) */
#include <avr/io.h>
#include <avr/wdt.h>
#include <avr/power.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <string.h>
#include <stdio.h>
#include <stdbool.h>
#include <stdint.h>
#if (F_CPU != 32000000)
#warning clock should better be 32MHz - USB needs it
#endif
/* initialize all the USB (terminal + disk)
* - also switches to 32MHz
* - enables medium priority interrupts
* - also enables global interrupts
*/
extern void USBInit(void);
/* process the USB */
extern void USBPoll(void);
/* the I/O steam of the USB terminal */
extern FILE *USBtty0;
#define USBdisk_sectorSize 512
/* Global number of 512 byte sectors the MassStorage
* disk should identify itself with
* Best initialized before "USBInit()".
*/
extern uint32_t USBdisk_sectorCount;
/* Global information about the type of the media
* Best initialized before "USBInit()".
*/
extern bool USBdisk_readOnly;
static volatile unsigned long abstinent_reads = 0;
static volatile unsigned long abstinent_writes = 0;
int main(void)
{
USBdisk_sectorCount = 256; /* = 128 KiB */
USBdisk_readOnly = true; /* forbid write */
/* Init the USB (and clock + interrupts) */
USBInit();
for (;;)
{
/* Must throw away unused bytes from the host */
int c = fgetc(USBtty0);
/* simple demo: implement an echo */
if (!(c<0)) {
fprintf_P(USBtty0, PSTR("%3lu sectors read, %3lu writes ignored, key pressed: %c\r\n"),
abstinent_reads, abstinent_writes, c);
abstinent_reads=0;
abstinent_writes=0;
}
USBPoll();
}
}
/* "USBdisk_CALLBACK_readSector" is called internally by the USB/SCSI stack.
* Its purpose is to:
* (1) read a sector "in_sectorNumber" (starting at 0),
* (2) put the secotors content into "out_sectordata"
* (3) return the number of bytes read - usually 512 (USBdisk_sectorSize).
*/
int16_t USBdisk_CALLBACK_readSector(uint8_t out_sectordata[USBdisk_sectorSize], const uint32_t in_sectorNumber)
{
/* increase the read counter */
abstinent_reads++;
/* "fill" the sector with some data, make it depend on "in_sectorNumber" to see the different sectors */
memset(&out_sectordata[0], ~(in_sectorNumber & 0xff), USBdisk_sectorSize);
return USBdisk_sectorSize;
}
/* "USBdisk_CALLBACK_writeSector" is called internally by the USB/SCSI stack.
* Its purpose is to:
* (1) put the content "in_sectordata" on the media at sector "in_sectorNumber"
* (2) return the number of bytes written - usually 512 (USBdisk_sectorSize).
*/
int16_t USBdisk_CALLBACK_writeSector(uint8_t in_sectordata[USBdisk_sectorSize], const uint32_t in_sectorNumber)
{
/* increase the write counter */
abstinent_writes++;
/* at the moment simply ignore the write - in case of readOnly it shouldn't be called anyway */
return USBdisk_sectorSize;
}