I am trying to work on an x86 operating system and coding it in C. My OS uses GRUB-Multiboot and thus far I have been able to get a GDT working.
I am currently working on my IDT and have run into a problem. When my OS boots up, it receives one IRQ and no further ones. I do have the keyboard line enabled and I should be receiving IRQs from that whenever I click a key but this is not the case.
What comes up upon startup:
Here is the code for idt.c:
#include <stdint.h>
#include "idt.h"
#include "lib/stdio.h"
#include "include/io.h"
// Define the Interrupt Descriptor Table (IDT)
struct idt_entry_t idt[IDT_ENTRIES];
struct idt_entry_t idt_entries[IDT_ENTRIES];
// Load the IDT pointer
struct idt_ptr_t idt_ptr = {
.limit = sizeof(idt) - 1,
.base = (uint32_t)&idt
};
typedef struct registers {
uint32_t ds; // Data segment selector
uint32_t edi, esi, ebp, esp, ebx, edx, ecx, eax; // Pushed by pusha
uint32_t int_no, err_code; // Interrupt number and error code (if applicable)
uint32_t eip, cs, eflags, useresp, ss; // Pushed by the processor automatically
} registers_t;
// Define an IRQ handler function
void irq_handler(registers_t *regs)
{
nanos_printf("Received an IRQ!\n");
// Send an EOI (end-of-interrupt) signal to the PICs
outb(0xA0, 0x20); // Send reset signal to slave
outb(0x20, 0x20); // Send reset signal to master
return;
}
void isr_handler()
{
nanos_printf("\n\nSTOP\n\nException occurred... halting...");
// Halt the CPU
for (;;);
}
void idt_load()
{
asm volatile("lidt %0" : : "m"(idt_ptr));
}
void idt_init(void)
{
// Disable interrupts
__asm__ __volatile__("cli");
// Setup the PIC(s)
outb(0x20, 0x11);
outb(0xA0, 0x11);
outb(0x21, 0x20);
outb(0xA1, 0x28);
outb(0x21, 0x04);
outb(0x21, 0x01);
outb(0x21, 0xFB);
outb(0xA1, 0xFF);
// Print a message to indicate that IDT is being loaded
nanos_printf("Loading IDT\n");
// Initialize the IDT pointer
idt_ptr.limit = sizeof(idt) - 1;
idt_ptr.base = (uint32_t)&idt;
// Set each IDT entry to the default handler
for (int i = 0; i < IDT_ENTRIES; i++)
{
idt_set_gate(i, (uint32_t)isr_handler, 0x08, 0x8E);
}
// Set the IRQ entries in the IDT
idt_set_gate(32, (uint32_t)irq_handler, 0x08, 0x8E);
idt_set_gate(33, (uint32_t)irq_handler, 0x08, 0x8E);
idt_set_gate(34, (uint32_t)irq_handler, 0x08, 0x8E);
idt_set_gate(35, (uint32_t)irq_handler, 0x08, 0x8E);
idt_set_gate(36, (uint32_t)irq_handler, 0x08, 0x8E);
idt_set_gate(37, (uint32_t)irq_handler, 0x08, 0x8E);
idt_set_gate(38, (uint32_t)irq_handler, 0x08, 0x8E);
idt_set_gate(39, (uint32_t)irq_handler, 0x08, 0x8E);
idt_set_gate(40, (uint32_t)irq_handler, 0x08, 0x8E);
idt_set_gate(41, (uint32_t)irq_handler, 0x08, 0x8E);
idt_set_gate(42, (uint32_t)irq_handler, 0x08, 0x8E);
idt_set_gate(43, (uint32_t)irq_handler, 0x08, 0x8E);
idt_set_gate(44, (uint32_t)irq_handler, 0x08, 0x8E);
idt_set_gate(45, (uint32_t)irq_handler, 0x08, 0x8E);
// Send initialization control word 1 and 2 to both PICs
outb(PIC1_COMMAND, ICW1_INIT | ICW1_ICW4); // Initialization Control Word 1
io_wait();
outb(PIC2_COMMAND, ICW1_INIT | ICW1_ICW4);
io_wait();
// Send initialization control word 3 to both PICs
outb(PIC1_DATA, 0x20); // Initialization Control Word 3: IRQ 0-7 map to IDT entries 0x20-0x27
io_wait();
outb(PIC2_DATA, 0x28); // Initialization Control Word 3: IRQ 8-15 map to IDT entries 0x28-0x2F
io_wait();
// Send initialization control word 4 to both PICs
outb(PIC1_DATA, ICW4_8086);
io_wait();
outb(PIC2_DATA, ICW4_8086);
io_wait();
// Unmask IRQs
outb(PIC1_DATA, 0x0);
outb(PIC2_DATA, 0x0);
// Load IDT
idt_load();
// Enable interrupts
__asm__ __volatile__("sti");
nanos_printf("IDT loaded\n");
}
void idt_set_gate(uint8_t num, uint32_t base, uint16_t sel, uint8_t flags)
{
// Set the base address
idt[num].base_lo = base & 0xFFFF;
idt[num].base_hi = (base >> 16) & 0xFFFF;
// Set the selector
idt[num].sel = sel;
// Set the always0 field
idt[num].always0 = 0;
// Set the flags
idt[num].flags = flags;
}
And here is idt.h:
#ifndef IDT_H
#define IDT_H
#include <stdint.h>
// Number of entries in the IDT
#define IDT_ENTRIES 256
// Struct for IDT entry
struct idt_entry_t {
uint16_t base_lo; // Lower 16 bits of handler function address
uint16_t sel; // Kernel segment selector
uint8_t always0; // Must always be zero
uint8_t flags; // Flags for entry (present, privilege level, type)
uint16_t base_hi; // Upper 16 bits of handler function address
} __attribute__((packed));
// Struct for IDT pointer
struct idt_ptr_t {
uint16_t limit; // Size of IDT
uint32_t base; // Base address of IDT
} __attribute__((packed));
// Define macros for setting flags in IDT entries
#define IDT_PRESENT_BIT 0x80
#define IDT_RING0 0x00
#define IDT_RING3 0x60
#define IDT_INT_GATE 0x0E
#define IDT_TRAP_GATE 0x0F
#define IDT_SIZE 0x08
// Define an IRQ handler function
void irq_handler();
// Define an ISR handler function
void isr_handler();
// Define a function to load the IDT
void idt_load();
// Define a function to initialize the IDT
void idt_init(void);
// Define a function to set a gate in the IDT
void idt_set_gate(uint8_t num, uint32_t base, uint16_t sel, uint8_t flags);
#endif // IDT_H
The issue seems to lie within the IRQ handler itself not returning. I do send reset signals to both the master and slave PIC inside of irq_handler() which is inside of idt.c.
And yes, I do have an infinite loop at the end of my kernel_main():
void kernel_main(void)
{
clear_screen();
nanos_printf("Hello NanOS!\n");
gdt_init();
nanos_printf("Initialized Global Descriptor Table.\n");
idt_init();
nanos_printf("Initialized Interrupt Descriptor Table.\n");
while (true) {}
}
Problem:
I tried to click keys on the keyboard to receive a keyboard IRQ but I only receive one IRQ at the start. I dabbled in OSDEV a few years back and from what I remember the PICs receive more than one IRQ upon startup anyways.
I'm trying to modify code that was initially designed for Trinket board (ATTiny85). It compiles properly for ESP8266-12E board (NodeMCU1.0). But unit is rebooting when loading image to memory.
Lines with:
memcpy_P(palette, imagePalette, 2 * 3);
Causing device to be rebooted.
I will be really greatfull if someone will advise me what should be modified to solve it? Code is taken from Github
Code:
#include <Arduino.h>
#include <Adafruit_DotStar.h>
#include <SPI.h> // Enable this line on Pro Trinket
typedef uint16_t line_t; // Bigger images OK on other boards
// CONFIGURABLE STUFF ------------------------------------------------------
#include "fire.h" // Graphics data is contained in this header file.
#define LED_DATA_PIN MOSI
#define LED_CLOCK_PIN SCK
#define SELECT_PIN 3
boolean autoCycle = false; // Set to true to cycle images by default
#define CYCLE_TIME 15 // Time, in seconds, between auto-cycle images
// -------------------------------------------------------------------------
#if defined(LED_DATA_PIN) && defined(LED_CLOCK_PIN)
// Older DotStar LEDs use GBR order. If colors are wrong, edit here.
Adafruit_DotStar strip = Adafruit_DotStar(NUM_LEDS,
LED_DATA_PIN, LED_CLOCK_PIN, DOTSTAR_BRG);
#else
Adafruit_DotStar strip = Adafruit_DotStar(NUM_LEDS, DOTSTAR_BRG);
#endif
void imageInit(void);
uint16_t readVoltage(void);
#ifdef MOTION_PIN
void sleep(void);
#endif
void setup() {
#if defined(__AVR_ATtiny85__) && (F_CPU == 16000000L)
clock_prescale_set(clock_div_1); // Enable 16 MHz on Trinket
#endif
#ifdef POWER_PIN
pinMode(POWER_PIN, OUTPUT);
digitalWrite(POWER_PIN, LOW); // Power-on LED strip
#endif
strip.begin(); // Allocate DotStar buffer, init SPI
strip.clear(); // Make sure strip is clear
strip.show(); // before measuring battery
imageInit(); // Initialize pointers for default image
#ifdef SELECT_PIN
pinMode(SELECT_PIN, INPUT_PULLUP);
#endif
}
// GLOBAL STATE STUFF ------------------------------------------------------
uint32_t lastImageTime = 0L; // Time of last image change
uint8_t imageNumber = 0, // Current image being displayed
imageType, // Image type: PALETTE[1,4,8] or TRUECOLOR
*imagePalette, // -> palette data in PROGMEM
*imagePixels, // -> pixel data in PROGMEM
palette[16][3]; // RAM-based color table for 1- or 4-bit images
line_t imageLines, // Number of lines in active image
imageLine; // Current line number in image
#ifdef SELECT_PIN
uint8_t debounce = 0; // Debounce counter for image select pin
#endif
void imageInit() { // Initialize global image state for current imageNumber
imageType = pgm_read_byte(&images[imageNumber].type);
imageLines = pgm_read_word(&images[imageNumber].lines);
imageLine = 0;
imagePalette = (uint8_t *)pgm_read_word(&images[imageNumber].palette);
imagePixels = (uint8_t *)pgm_read_word(&images[imageNumber].pixels);
if(imageType == PALETTE1) memcpy_P(palette, imagePalette, 2 * 3);
else if(imageType == PALETTE4) memcpy_P(palette, imagePalette, 16 * 3);
lastImageTime = millis(); // Save time of image init for next auto-cycle
}
void nextImage(void) {
if(++imageNumber >= NUM_IMAGES) imageNumber = 0;
imageInit();
}
// MAIN LOOP ---------------------------------------------------------------
void loop() {
uint32_t t = millis(); // Current time, milliseconds
if(autoCycle) {
if((t - lastImageTime) >= (CYCLE_TIME * 1000L)) nextImage();
// CPU clocks vary slightly; multiple poi won't stay in perfect sync.
// Keep this in mind when using auto-cycle mode, you may want to cull
// the image selection to avoid unintentional regrettable combinations.
}
#ifdef SELECT_PIN
if(digitalRead(SELECT_PIN)) { // Image select?
debounce = 0; // Not pressed -- reset counter
} else { // Pressed...
if(++debounce >= 25) { // Debounce input
nextImage(); // Switch to next image
while(!digitalRead(SELECT_PIN)); // Wait for release
// If held 1+ sec, toggle auto-cycle mode on/off
if((millis() - t) >= 1000L) autoCycle = !autoCycle;
debounce = 0;
}
}
#endif
switch(imageType) {
case PALETTE1: { // 1-bit (2 color) palette-based image
uint8_t pixelNum = 0, byteNum, bitNum, pixels, idx,
*ptr = (uint8_t *)&imagePixels[imageLine * NUM_LEDS / 8];
for(byteNum = NUM_LEDS/8; byteNum--; ) { // Always padded to next byte
pixels = pgm_read_byte(ptr++); // 8 pixels of data (pixel 0 = LSB)
for(bitNum = 8; bitNum--; pixels >>= 1) {
idx = pixels & 1; // Color table index for pixel (0 or 1)
strip.setPixelColor(pixelNum++,
palette[idx][0], palette[idx][1], palette[idx][2]);
}
}
break;
}
case PALETTE4: { // 4-bit (16 color) palette-based image
uint8_t pixelNum, p1, p2,
*ptr = (uint8_t *)&imagePixels[imageLine * NUM_LEDS / 2];
for(pixelNum = 0; pixelNum < NUM_LEDS; ) {
p2 = pgm_read_byte(ptr++); // Data for two pixels...
p1 = p2 >> 4; // Shift down 4 bits for first pixel
p2 &= 0x0F; // Mask out low 4 bits for second pixel
strip.setPixelColor(pixelNum++,
palette[p1][0], palette[p1][1], palette[p1][2]);
strip.setPixelColor(pixelNum++,
palette[p2][0], palette[p2][1], palette[p2][2]);
}
break;
}
}
strip.show(); // Refresh LEDs
delayMicroseconds(900);
if(++imageLine >= imageLines) imageLine = 0; // Next scanline, wrap around
}
And fire.h file:
// Don't edit this file! It's software-generated.
// See convert.py script instead.
#define PALETTE1 0
#define PALETTE4 1
#define PALETTE8 2
#define TRUECOLOR 3
#define NUM_LEDS 16
// fire.gif ----------------------------------------------------------------
const uint8_t PROGMEM palette00[][3] = {
{ 88, 80, 3 },
{ 88, 88, 23 },
{ 88, 34, 0 },
{ 88, 4, 0 },
{ 88, 49, 0 },
{ 88, 9, 0 },
{ 0, 0, 0 },
{ 88, 88, 10 },
{ 88, 17, 0 },
{ 16, 0, 0 },
{ 88, 1, 0 },
{ 88, 0, 0 },
{ 88, 68, 1 },
{ 33, 0, 0 },
{ 1, 0, 0 },
{ 7, 0, 0 } };
const uint8_t PROGMEM pixels00[] = {
0X66, 0X6E, 0X95, 0XC7, 0X05, 0XD9, 0XEB, 0XE6,
0X66, 0X6E, 0X93, 0XCC, 0X4A, 0X9F, 0X9B, 0XE6,
0X66, 0X66, 0X93, 0X4C, 0X8D, 0X99, 0XB9, 0XE6,
0X66, 0X6E, 0XD3, 0X42, 0X39, 0X9B, 0XB9, 0XE6,
0X66, 0X6F, 0XD5, 0X88, 0XD9, 0X9B, 0XB9, 0XE6,
0X66, 0X6F, 0XB8, 0X23, 0XDF, 0X9B, 0XBD, 0XE6,
0X66, 0XE9, 0XA8, 0X2A, 0X9E, 0X9B, 0XBD, 0XF6,
0X66, 0XE9, 0X32, 0X8B, 0XFE, 0X9B, 0XAB, 0XDE,
0X66, 0XED, 0X52, 0X5D, 0XE6, 0XFB, 0XA3, 0XB9,
0X66, 0XFB, 0X22, 0X59, 0XE6, 0XED, 0XA3, 0XAD,
0X66, 0X9A, 0X24, 0X39, 0X66, 0XEF, 0XA3, 0X3B,
0X6E, 0XF3, 0X24, 0X39, 0XE6, 0X6F, 0XD3, 0X3B,
0X66, 0X93, 0X44, 0X39, 0XE6, 0X6E, 0X93, 0X3A,
0X6E, 0X93, 0X44, 0X59, 0X66, 0X6E, 0X93, 0X5A,
0X6E, 0X93, 0X2C, 0X59, 0XE6, 0X6E, 0XD3, 0X5A,
0X66, 0X9A, 0X44, 0X8D, 0XF6, 0XEF, 0XA8, 0X8A,
0X66, 0XFA, 0X2C, 0X45, 0X9F, 0XFD, 0X52, 0X8B,
0X66, 0XED, 0X8C, 0X04, 0X5D, 0XD8, 0X44, 0X3D,
0X66, 0XE9, 0X3C, 0X77, 0XC4, 0X4C, 0XC4, 0XA9,
0X66, 0X69, 0XAC, 0X71, 0X77, 0X77, 0XC5, 0XBF,
0X66, 0XEF, 0XB2, 0X71, 0X11, 0X70, 0X2A, 0X9E,
0X66, 0X6F, 0XD8, 0X01, 0X11, 0X74, 0XA9, 0XF6,
0X66, 0X6E, 0X93, 0XC1, 0X17, 0XC3, 0XDE, 0X66,
0X6E, 0X6E, 0XFA, 0X47, 0X17, 0X2D, 0XF6, 0X66,
0X6E, 0XBF, 0XFD, 0X50, 0X7C, 0X89, 0XE6, 0X66,
0X6E, 0XBF, 0XFD, 0XA4, 0XCC, 0X39, 0XE6, 0X66,
0X6E, 0XFB, 0X9F, 0XD8, 0X44, 0X39, 0XE6, 0X66,
0X6E, 0X9B, 0XBD, 0X93, 0X22, 0X39, 0XE6, 0X66,
0X6E, 0XFB, 0XB9, 0X9D, 0X52, 0X5D, 0XE6, 0X66,
0X6E, 0XDB, 0XB9, 0XF9, 0X32, 0X8A, 0XF6, 0X66,
0X6F, 0XDB, 0XB9, 0XFF, 0XA2, 0X8A, 0X9E, 0X66,
0XED, 0XBA, 0XB9, 0XE9, 0XB8, 0X23, 0X9E, 0X66,
0X9B, 0XA3, 0XBF, 0XEE, 0XD5, 0X25, 0XDF, 0X66,
0X9A, 0X3A, 0XDF, 0X6E, 0X93, 0X28, 0XBF, 0X66,
0XB3, 0X5B, 0X96, 0X66, 0X93, 0X22, 0XAF, 0XE6,
0XB3, 0X3D, 0XE6, 0X6E, 0X93, 0X24, 0X39, 0XE6,
0XA3, 0X39, 0XE6, 0X66, 0X93, 0X42, 0X39, 0XE6,
0XA5, 0X39, 0XE6, 0X6E, 0X93, 0X44, 0X39, 0XE6,
0XA5, 0X3D, 0XE6, 0X66, 0XD5, 0X44, 0XA9, 0X66,
0XA8, 0X8A, 0X96, 0X6F, 0XD2, 0X44, 0XAF, 0X66,
0XB8, 0X25, 0XD9, 0XFD, 0X3C, 0XC8, 0XAF, 0XE6,
0XD5, 0X44, 0X5D, 0XD3, 0XC0, 0X08, 0XDE, 0X66,
0X9A, 0X20, 0XC4, 0X4C, 0X77, 0XC3, 0XDE, 0X66,
0XFB, 0X8C, 0X77, 0X71, 0X71, 0X43, 0XFE, 0X66,
0XE9, 0XA2, 0X01, 0X11, 0X17, 0X4B, 0XF6, 0X66,
0X6E, 0XDA, 0X47, 0X11, 0X17, 0X8D, 0XF6, 0X66,
0X66, 0XE9, 0X3C, 0X11, 0X1C, 0X39, 0XE6, 0X66,
0X66, 0X6F, 0XD2, 0X71, 0X74, 0XAF, 0XEE, 0X66 };
typedef struct {
uint8_t type; // PALETTE[1,4,8] or TRUECOLOR
line_t lines; // Length of image (in scanlines)
const uint8_t *palette; // -> PROGMEM color table (NULL if truecolor)
const uint8_t *pixels; // -> Pixel data in PROGMEM
} image;
const image PROGMEM images[] = {
{ PALETTE4 , 48, (const uint8_t *)palette00, pixels00 }
};
#define NUM_IMAGES (sizeof(images) / sizeof(images[0]))
Error code: (I have added Serial.Print information before each line of code that way I know there is someting with memcpy_P)
Loading pgm_read_byte... OK !
Loading pgm_read_word... OK !
Loading PALETTE1 memcpy_P...
Exception (28):
epc1=0x40202fda epc2=0x00000000 epc3=0x00000000 excvaddr=0x000078ec depc=0x00000000
ctx: cont
sp: 3ffef830 end: 3ffefa40 offset: 01a0
>>>stack>>>
3ffef9d0: 3ffe8910 3ffee7d0 00000001 402022d6
3ffef9e0: 00000000 00000001 3ffee9ec 3ffe8910
3ffef9f0: 3ffee7c4 3ffe88ec 3ffee9ec 40201ff9
3ffefa00: 0001c200 0000001c 3ffee7d0 3ffeea10
3ffefa10: 3fffdad0 00000000 3ffee7d0 40202051
3ffefa20: feefeffe feefeffe 3ffeea08 40202d60
3ffefa30: feefeffe feefeffe 3ffeea20 4010070c
<<<stack<<<
Decoded error with avr decoder:
Exception 28: LoadProhibited: A load referenced a page mapped with an attribute that does not permit loads
Decoding 6 results
0x40202fda: pgm_read_byte_inlined at C:\Users\Rafal\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.4.0-rc2\cores\esp8266/pgmspace.h line 104
0x402022d6: Adafruit_DotStar::sw_spi_out(unsigned char) at D:\Dropbox\ArduinoLib\libraries\Adafruit_DotStar/Adafruit_DotStar.cpp line 40
0x40201ff9: imageInit() at D:\Dropbox\ArduinoLib\sketch_nov16b/sketch_nov16b.ino line 167
0x40202051: setup at D:\Dropbox\ArduinoLib\sketch_nov16b/sketch_nov16b.ino line 125
0x40202d60: loop_wrapper at C:\Users\Rafal\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.4.0-rc2\cores\esp8266/core_esp8266_main.cpp line 57
0x4010070c: cont_norm at C:\Users\Rafal\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.4.0-rc2\cores\esp8266/cont.S line 109
BTW. I have tried multiple versions of boards 2.3.0, 2.4.0 RC1 and RC2.
I was able to get the adafruit code you posted above working with ESP8266 by deleting all of the instances of PROGMEM from the sketch. Just use find and replace function in arduino and delete all progmem and replace with nothing. Then replace imageinit with the one below from the supernova sketch. It does work but it stores all the patterns in working memory, not in flash. I am now trying to get patterns stored in flash so more patterns can be stored.
void imageInit() { // Initialize global image state for current imageNumber
imageType = images[imageNumber].type;
imageLines = images[imageNumber].lines;
imageLine = 0;
imagePalette = (uint8_t *)images[imageNumber].palette;
imagePixels = (uint8_t *)images[imageNumber].pixels;
// 1- and 4-bit images have their color palette loaded into RAM both for
// faster access and to allow dynamic color changing. Not done w/8-bit
// because that would require inordinate RAM (328P could handle it, but
// I'd rather keep the RAM free for other features in the future).
if(imageType == PALETTE1) memcpy_P(palette, imagePalette, 2 * 3);
else if(imageType == PALETTE4) memcpy_P(palette, imagePalette, 16 * 3);
lastImageTime = millis(); // Save time of image init for next auto-cycle
}
I am having problems with calculating CRC-16 implementation of a byte array in java. Basically I am trying to send bytes to a RFID that starts writing to a tag. I can see the checksum value of array by looking tcpdump command on mac. But my goal is to generate it by myself. Here is my byte array which should generate 0xbe,0xd9:
byte[] bytes = new byte[]{(byte) 0x55,(byte) 0x08,(byte) 0x68, (byte) 0x14,
(byte) 0x93, (byte) 0x01, (byte) 0x00, (byte) 0x00,
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x06,
(byte) 0x00, (byte) 0x00, (byte) 0x01, (byte) 0x00,
(byte) 0x13, (byte) 0x50, (byte) 0x00, (byte) 0x00,
(byte) 0x00, (byte) 0x22, (byte) 0x09, (byte) 0x11};
0x55 is the header. As the documentation says it will be excluded.
Whenever I try this array on java (with 0xbe,0xd9), RFID works. My problem is the generating of those checksum values. I searched almost entire web but no chance. I couldn't find any algorithm that produces 0xbe,0xd9.
Any idea is most welcome for me. Thanks in advance.
edit: here is the protocol that provided with rfid
I'm not really sure if this is the correct translation in Java of the C crc16 algorithm....
but it shows the correct result for your example!
Please compare other results with Mac's CRC16 and stress-test it before using it.
public class Crc16 {
public static void main(String... a) {
byte[] bytes = new byte[] { (byte) 0x08, (byte) 0x68, (byte) 0x14, (byte) 0x93, (byte) 0x01, (byte) 0x00,
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x06, (byte) 0x00, (byte) 0x00, (byte) 0x01,
(byte) 0x00, (byte) 0x13, (byte) 0x50, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x22, (byte) 0x09,
(byte) 0x11 };
byte[] byteStr = new byte[4];
Integer crcRes = new Crc16().calculate_crc(bytes);
System.out.println(Integer.toHexString(crcRes));
byteStr[0] = (byte) ((crcRes & 0x000000ff));
byteStr[1] = (byte) ((crcRes & 0x0000ff00) >>> 8);
System.out.printf("%02X\n%02X", byteStr[0],byteStr[1]);
}
int calculate_crc(byte[] bytes) {
int i;
int crc_value = 0;
for (int len = 0; len < bytes.length; len++) {
for (i = 0x80; i != 0; i >>= 1) {
if ((crc_value & 0x8000) != 0) {
crc_value = (crc_value << 1) ^ 0x8005;
} else {
crc_value = crc_value << 1;
}
if ((bytes[len] & i) != 0) {
crc_value ^= 0x8005;
}
}
}
return crc_value;
}
}
There is a CRC16 implementation in the Java runtime (rt.jar) already.
Please see grepcode for the source.
You will probably be able to see it in your IDE if you search for CRC16:
Maybe are you looking for this?
Crc16 in java
I use the same array (variable "table") in this method:
public Integer computeCrc16(byte[] data) {
int crc = 0x0000;
for (byte b : data) {
crc = (crc >>> 8) ^ table[((crc ^ b) & 0xff)];
}
return (int) crc;
}
if you want ASCII character then change
byte[] bytes="02303131313233343031303345303903".getBytes();
Below is correct answer for HEX input ,
byte[] bytes = hexStringToByteArray("02303131313233343031303345303903");
public class CRC16 {
public static void main(String[] args) {
int[] table = {
0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241,
0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440,
0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40,
0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841,
0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40,
0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41,
0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641,
0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040,
0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240,
0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441,
0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41,
0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840,
0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41,
0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40,
0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640,
0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041,
0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240,
0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441,
0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41,
0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840,
0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41,
0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40,
0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640,
0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041,
0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241,
0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440,
0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40,
0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841,
0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40,
0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41,
0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641,
0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040,
};
byte[] bytes = hexStringToByteArray("02303131313233343031303345303903"); // for HEX
int crc16 = 0x0000;
for (byte b : bytes) {
crc16=table[(crc16 ^ b) & 0xff] ^ (crc16 >> 8);
}
crc16= crc16 & 0xFFFF;
System.out.println("CRC16 = " +Integer.toHexString(crc16));
}
public static byte[] hexStringToByteArray(String s) {
int len = s.length();
byte[] data = new byte[len / 2];
for (int i = 0; i < len; i += 2) {
data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)+ Character.digit(s.charAt(i+1), 16));
}
return data;
}
}