4 #define TAPPING_TERM 200
7 static void do_code16 (uint16_t code, void (*f) (uint8_t)) {
9 case QK_MODS ... QK_MODS_MAX:
24 if (code < QK_RMODS_MIN) return;
36 static inline void qk_register_mods(uint8_t kc) {
37 register_mods(MOD_BIT(kc));
40 static inline void qk_unregister_mods(uint8_t kc) {
41 unregister_mods(MOD_BIT(kc));
44 void register_code16 (uint16_t code) {
45 do_code16 (code, qk_register_mods);
49 void unregister_code16 (uint16_t code) {
50 unregister_code (code);
51 do_code16 (code, qk_unregister_mods);
54 __attribute__ ((weak))
55 bool process_action_kb(keyrecord_t *record) {
59 __attribute__ ((weak))
60 bool process_record_kb(uint16_t keycode, keyrecord_t *record) {
61 return process_record_user(keycode, record);
64 __attribute__ ((weak))
65 bool process_record_user(uint16_t keycode, keyrecord_t *record) {
69 void reset_keyboard(void) {
76 #ifdef CATERINA_BOOTLOADER
77 *(uint16_t *)0x0800 = 0x7777; // these two are a-star-specific
82 // Shift / paren setup
91 static bool shift_interrupted[2] = {0, 0};
92 static uint16_t scs_timer = 0;
94 bool process_record_quantum(keyrecord_t *record) {
96 /* This gets the keycode from the key pressed */
97 keypos_t key = record->event.key;
100 #if !defined(NO_ACTION_LAYER) && defined(PREVENT_STUCK_MODIFIERS)
101 /* TODO: Use store_or_get_action() or a similar function. */
102 if (!disable_action_cache) {
105 if (record->event.pressed) {
106 layer = layer_switch_get_layer(key);
107 update_source_layers_cache(key, layer);
109 layer = read_source_layers_cache(key);
111 keycode = keymap_key_to_keycode(layer, key);
114 keycode = keymap_key_to_keycode(layer_switch_get_layer(key), key);
116 // This is how you use actions here
117 // if (keycode == KC_LEAD) {
119 // action.code = ACTION_DEFAULT_LAYER_SET(0);
120 // process_action(record, action);
125 process_record_kb(keycode, record) &&
127 process_midi(keycode, record) &&
130 process_music(keycode, record) &&
132 #ifdef TAP_DANCE_ENABLE
133 process_tap_dance(keycode, record) &&
135 #ifndef DISABLE_LEADER
136 process_leader(keycode, record) &&
138 #ifndef DISABLE_CHORDING
139 process_chording(keycode, record) &&
141 #ifdef UNICODE_ENABLE
142 process_unicode(keycode, record) &&
145 process_ucis(keycode, record) &&
147 #ifdef PRINTING_ENABLE
148 process_printer(keycode, record) &&
150 #ifdef UNICODEMAP_ENABLE
151 process_unicode_map(keycode, record) &&
157 // Shift / paren setup
161 if (record->event.pressed) {
167 if (record->event.pressed) {
168 print("\nDEBUG: enabled.\n");
173 #ifdef RGBLIGHT_ENABLE
175 if (record->event.pressed) {
181 if (record->event.pressed) {
187 if (record->event.pressed) {
188 rgblight_increase_hue();
193 if (record->event.pressed) {
194 rgblight_decrease_hue();
199 if (record->event.pressed) {
200 rgblight_increase_sat();
205 if (record->event.pressed) {
206 rgblight_decrease_sat();
211 if (record->event.pressed) {
212 rgblight_increase_val();
217 if (record->event.pressed) {
218 rgblight_decrease_val();
223 case MAGIC_SWAP_CONTROL_CAPSLOCK ... MAGIC_TOGGLE_NKRO:
224 if (record->event.pressed) {
225 // MAGIC actions (BOOTMAGIC without the boot)
226 if (!eeconfig_is_enabled()) {
230 keymap_config.raw = eeconfig_read_keymap();
233 case MAGIC_SWAP_CONTROL_CAPSLOCK:
234 keymap_config.swap_control_capslock = true;
236 case MAGIC_CAPSLOCK_TO_CONTROL:
237 keymap_config.capslock_to_control = true;
239 case MAGIC_SWAP_LALT_LGUI:
240 keymap_config.swap_lalt_lgui = true;
242 case MAGIC_SWAP_RALT_RGUI:
243 keymap_config.swap_ralt_rgui = true;
246 keymap_config.no_gui = true;
248 case MAGIC_SWAP_GRAVE_ESC:
249 keymap_config.swap_grave_esc = true;
251 case MAGIC_SWAP_BACKSLASH_BACKSPACE:
252 keymap_config.swap_backslash_backspace = true;
254 case MAGIC_HOST_NKRO:
255 keymap_config.nkro = true;
257 case MAGIC_SWAP_ALT_GUI:
258 keymap_config.swap_lalt_lgui = true;
259 keymap_config.swap_ralt_rgui = true;
261 case MAGIC_UNSWAP_CONTROL_CAPSLOCK:
262 keymap_config.swap_control_capslock = false;
264 case MAGIC_UNCAPSLOCK_TO_CONTROL:
265 keymap_config.capslock_to_control = false;
267 case MAGIC_UNSWAP_LALT_LGUI:
268 keymap_config.swap_lalt_lgui = false;
270 case MAGIC_UNSWAP_RALT_RGUI:
271 keymap_config.swap_ralt_rgui = false;
274 keymap_config.no_gui = false;
276 case MAGIC_UNSWAP_GRAVE_ESC:
277 keymap_config.swap_grave_esc = false;
279 case MAGIC_UNSWAP_BACKSLASH_BACKSPACE:
280 keymap_config.swap_backslash_backspace = false;
282 case MAGIC_UNHOST_NKRO:
283 keymap_config.nkro = false;
285 case MAGIC_UNSWAP_ALT_GUI:
286 keymap_config.swap_lalt_lgui = false;
287 keymap_config.swap_ralt_rgui = false;
289 case MAGIC_TOGGLE_NKRO:
290 keymap_config.nkro = !keymap_config.nkro;
295 eeconfig_update_keymap(keymap_config.raw);
296 clear_keyboard(); // clear to prevent stuck keys
302 if (record->event.pressed) {
303 shift_interrupted[0] = false;
304 scs_timer = timer_read ();
305 register_mods(MOD_BIT(KC_LSFT));
308 #ifdef DISABLE_SPACE_CADET_ROLLOVER
309 if (get_mods() & MOD_BIT(KC_RSFT)) {
310 shift_interrupted[0] = true;
311 shift_interrupted[1] = true;
314 if (!shift_interrupted[0] && timer_elapsed(scs_timer) < TAPPING_TERM) {
315 register_code(LSPO_KEY);
316 unregister_code(LSPO_KEY);
318 unregister_mods(MOD_BIT(KC_LSFT));
325 if (record->event.pressed) {
326 shift_interrupted[1] = false;
327 scs_timer = timer_read ();
328 register_mods(MOD_BIT(KC_RSFT));
331 #ifdef DISABLE_SPACE_CADET_ROLLOVER
332 if (get_mods() & MOD_BIT(KC_LSFT)) {
333 shift_interrupted[0] = true;
334 shift_interrupted[1] = true;
337 if (!shift_interrupted[1] && timer_elapsed(scs_timer) < TAPPING_TERM) {
338 register_code(RSPC_KEY);
339 unregister_code(RSPC_KEY);
341 unregister_mods(MOD_BIT(KC_RSFT));
347 shift_interrupted[0] = true;
348 shift_interrupted[1] = true;
353 return process_action_kb(record);
356 const bool ascii_to_qwerty_shift_lut[0x80] PROGMEM = {
357 0, 0, 0, 0, 0, 0, 0, 0,
358 0, 0, 0, 0, 0, 0, 0, 0,
359 0, 0, 0, 0, 0, 0, 0, 0,
360 0, 0, 0, 0, 0, 0, 0, 0,
361 0, 1, 1, 1, 1, 1, 1, 0,
362 1, 1, 1, 1, 0, 0, 0, 0,
363 0, 0, 0, 0, 0, 0, 0, 0,
364 0, 0, 1, 0, 1, 0, 1, 1,
365 1, 1, 1, 1, 1, 1, 1, 1,
366 1, 1, 1, 1, 1, 1, 1, 1,
367 1, 1, 1, 1, 1, 1, 1, 1,
368 1, 1, 1, 0, 0, 0, 1, 1,
369 0, 0, 0, 0, 0, 0, 0, 0,
370 0, 0, 0, 0, 0, 0, 0, 0,
371 0, 0, 0, 0, 0, 0, 0, 0,
372 0, 0, 0, 1, 1, 1, 1, 0
375 const uint8_t ascii_to_qwerty_keycode_lut[0x80] PROGMEM = {
376 0, 0, 0, 0, 0, 0, 0, 0,
377 KC_BSPC, KC_TAB, KC_ENT, 0, 0, 0, 0, 0,
378 0, 0, 0, 0, 0, 0, 0, 0,
379 0, 0, 0, KC_ESC, 0, 0, 0, 0,
380 KC_SPC, KC_1, KC_QUOT, KC_3, KC_4, KC_5, KC_7, KC_QUOT,
381 KC_9, KC_0, KC_8, KC_EQL, KC_COMM, KC_MINS, KC_DOT, KC_SLSH,
382 KC_0, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7,
383 KC_8, KC_9, KC_SCLN, KC_SCLN, KC_COMM, KC_EQL, KC_DOT, KC_SLSH,
384 KC_2, KC_A, KC_B, KC_C, KC_D, KC_E, KC_F, KC_G,
385 KC_H, KC_I, KC_J, KC_K, KC_L, KC_M, KC_N, KC_O,
386 KC_P, KC_Q, KC_R, KC_S, KC_T, KC_U, KC_V, KC_W,
387 KC_X, KC_Y, KC_Z, KC_LBRC, KC_BSLS, KC_RBRC, KC_6, KC_MINS,
388 KC_GRV, KC_A, KC_B, KC_C, KC_D, KC_E, KC_F, KC_G,
389 KC_H, KC_I, KC_J, KC_K, KC_L, KC_M, KC_N, KC_O,
390 KC_P, KC_Q, KC_R, KC_S, KC_T, KC_U, KC_V, KC_W,
391 KC_X, KC_Y, KC_Z, KC_LBRC, KC_BSLS, KC_RBRC, KC_GRV, KC_DEL
394 /* for users whose OSes are set to Colemak */
396 #include "keymap_colemak.h"
398 const bool ascii_to_colemak_shift_lut[0x80] PROGMEM = {
399 0, 0, 0, 0, 0, 0, 0, 0,
400 0, 0, 0, 0, 0, 0, 0, 0,
401 0, 0, 0, 0, 0, 0, 0, 0,
402 0, 0, 0, 0, 0, 0, 0, 0,
403 0, 1, 1, 1, 1, 1, 1, 0,
404 1, 1, 1, 1, 0, 0, 0, 0,
405 0, 0, 0, 0, 0, 0, 0, 0,
406 0, 0, 1, 0, 1, 0, 1, 1,
407 1, 1, 1, 1, 1, 1, 1, 1,
408 1, 1, 1, 1, 1, 1, 1, 1,
409 1, 1, 1, 1, 1, 1, 1, 1,
410 1, 1, 1, 0, 0, 0, 1, 1,
411 0, 0, 0, 0, 0, 0, 0, 0,
412 0, 0, 0, 0, 0, 0, 0, 0,
413 0, 0, 0, 0, 0, 0, 0, 0,
414 0, 0, 0, 1, 1, 1, 1, 0
417 const uint8_t ascii_to_colemak_keycode_lut[0x80] PROGMEM = {
418 0, 0, 0, 0, 0, 0, 0, 0,
419 KC_BSPC, KC_TAB, KC_ENT, 0, 0, 0, 0, 0,
420 0, 0, 0, 0, 0, 0, 0, 0,
421 0, 0, 0, KC_ESC, 0, 0, 0, 0,
422 KC_SPC, KC_1, KC_QUOT, KC_3, KC_4, KC_5, KC_7, KC_QUOT,
423 KC_9, KC_0, KC_8, KC_EQL, KC_COMM, KC_MINS, KC_DOT, KC_SLSH,
424 KC_0, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7,
425 KC_8, KC_9, CM_SCLN, CM_SCLN, KC_COMM, KC_EQL, KC_DOT, KC_SLSH,
426 KC_2, CM_A, CM_B, CM_C, CM_D, CM_E, CM_F, CM_G,
427 CM_H, CM_I, CM_J, CM_K, CM_L, CM_M, CM_N, CM_O,
428 CM_P, CM_Q, CM_R, CM_S, CM_T, CM_U, CM_V, CM_W,
429 CM_X, CM_Y, CM_Z, KC_LBRC, KC_BSLS, KC_RBRC, KC_6, KC_MINS,
430 KC_GRV, CM_A, CM_B, CM_C, CM_D, CM_E, CM_F, CM_G,
431 CM_H, CM_I, CM_J, CM_K, CM_L, CM_M, CM_N, CM_O,
432 CM_P, CM_Q, CM_R, CM_S, CM_T, CM_U, CM_V, CM_W,
433 CM_X, CM_Y, CM_Z, KC_LBRC, KC_BSLS, KC_RBRC, KC_GRV, KC_DEL
438 void send_string(const char *str) {
441 uint8_t ascii_code = pgm_read_byte(str);
442 if (!ascii_code) break;
443 keycode = pgm_read_byte(&ascii_to_qwerty_keycode_lut[ascii_code]);
444 if (pgm_read_byte(&ascii_to_qwerty_shift_lut[ascii_code])) {
445 register_code(KC_LSFT);
446 register_code(keycode);
447 unregister_code(keycode);
448 unregister_code(KC_LSFT);
451 register_code(keycode);
452 unregister_code(keycode);
458 void update_tri_layer(uint8_t layer1, uint8_t layer2, uint8_t layer3) {
459 if (IS_LAYER_ON(layer1) && IS_LAYER_ON(layer2)) {
466 void tap_random_base64(void) {
467 #if defined(__AVR_ATmega32U4__)
468 uint8_t key = (TCNT0 + TCNT1 + TCNT3 + TCNT4) % 64;
470 uint8_t key = rand() % 64;
474 register_code(KC_LSFT);
475 register_code(key + KC_A);
476 unregister_code(key + KC_A);
477 unregister_code(KC_LSFT);
480 register_code(key - 26 + KC_A);
481 unregister_code(key - 26 + KC_A);
485 unregister_code(KC_0);
488 register_code(key - 53 + KC_1);
489 unregister_code(key - 53 + KC_1);
492 register_code(KC_LSFT);
493 register_code(KC_EQL);
494 unregister_code(KC_EQL);
495 unregister_code(KC_LSFT);
498 register_code(KC_SLSH);
499 unregister_code(KC_SLSH);
504 void matrix_init_quantum() {
505 #ifdef BACKLIGHT_ENABLE
506 backlight_init_ports();
511 void matrix_scan_quantum() {
516 #ifdef TAP_DANCE_ENABLE
517 matrix_scan_tap_dance();
522 #if defined(BACKLIGHT_ENABLE) && defined(BACKLIGHT_PIN)
524 static const uint8_t backlight_pin = BACKLIGHT_PIN;
526 #if BACKLIGHT_PIN == B7
527 # define COM1x1 COM1C1
529 #elif BACKLIGHT_PIN == B6
530 # define COM1x1 COM1B1
532 #elif BACKLIGHT_PIN == B5
533 # define COM1x1 COM1A1
536 # error "Backlight pin not supported - use B5, B6, or B7"
539 __attribute__ ((weak))
540 void backlight_init_ports(void)
543 // Setup backlight pin as output and output low.
545 _SFR_IO8((backlight_pin >> 4) + 1) |= _BV(backlight_pin & 0xF);
547 _SFR_IO8((backlight_pin >> 4) + 2) &= ~_BV(backlight_pin & 0xF);
549 // Use full 16-bit resolution.
552 // I could write a wall of text here to explain... but TL;DW
553 // Go read the ATmega32u4 datasheet.
554 // And this: http://blog.saikoled.com/post/43165849837/secret-konami-cheat-code-to-high-resolution-pwm-on
556 // Pin PB7 = OCR1C (Timer 1, Channel C)
557 // Compare Output Mode = Clear on compare match, Channel C = COM1C1=1 COM1C0=0
558 // (i.e. start high, go low when counter matches.)
559 // WGM Mode 14 (Fast PWM) = WGM13=1 WGM12=1 WGM11=1 WGM10=0
560 // Clock Select = clk/1 (no prescaling) = CS12=0 CS11=0 CS10=1
562 TCCR1A = _BV(COM1x1) | _BV(WGM11); // = 0b00001010;
563 TCCR1B = _BV(WGM13) | _BV(WGM12) | _BV(CS10); // = 0b00011001;
566 #ifdef BACKLIGHT_BREATHING
567 breathing_defaults();
571 __attribute__ ((weak))
572 void backlight_set(uint8_t level)
574 // Prevent backlight blink on lowest level
576 _SFR_IO8((backlight_pin >> 4) + 2) &= ~_BV(backlight_pin & 0xF);
579 // Turn off PWM control on backlight pin, revert to output low.
580 TCCR1A &= ~(_BV(COM1x1));
582 } else if ( level == BACKLIGHT_LEVELS ) {
583 // Turn on PWM control of backlight pin
584 TCCR1A |= _BV(COM1x1);
585 // Set the brightness
588 // Turn on PWM control of backlight pin
589 TCCR1A |= _BV(COM1x1);
590 // Set the brightness
591 OCR1x = 0xFFFF >> ((BACKLIGHT_LEVELS - level) * ((BACKLIGHT_LEVELS + 1) / 2));
594 #ifdef BACKLIGHT_BREATHING
595 breathing_intensity_default();
600 #ifdef BACKLIGHT_BREATHING
602 #define BREATHING_NO_HALT 0
603 #define BREATHING_HALT_OFF 1
604 #define BREATHING_HALT_ON 2
606 static uint8_t breath_intensity;
607 static uint8_t breath_speed;
608 static uint16_t breathing_index;
609 static uint8_t breathing_halt;
611 void breathing_enable(void)
613 if (get_backlight_level() == 0)
619 // Set breathing_index to be at the midpoint (brightest point)
620 breathing_index = 0x20 << breath_speed;
623 breathing_halt = BREATHING_NO_HALT;
625 // Enable breathing interrupt
626 TIMSK1 |= _BV(OCIE1A);
629 void breathing_pulse(void)
631 if (get_backlight_level() == 0)
637 // Set breathing_index to be at the midpoint + 1 (brightest point)
638 breathing_index = 0x21 << breath_speed;
641 breathing_halt = BREATHING_HALT_ON;
643 // Enable breathing interrupt
644 TIMSK1 |= _BV(OCIE1A);
647 void breathing_disable(void)
649 // Disable breathing interrupt
650 TIMSK1 &= ~_BV(OCIE1A);
651 backlight_set(get_backlight_level());
654 void breathing_self_disable(void)
656 if (get_backlight_level() == 0)
658 breathing_halt = BREATHING_HALT_OFF;
662 breathing_halt = BREATHING_HALT_ON;
665 //backlight_set(get_backlight_level());
668 void breathing_toggle(void)
672 if (get_backlight_level() == 0)
678 // Set breathing_index to be at the midpoint + 1 (brightest point)
679 breathing_index = 0x21 << breath_speed;
682 breathing_halt = BREATHING_NO_HALT;
685 // Toggle breathing interrupt
686 TIMSK1 ^= _BV(OCIE1A);
688 // Restore backlight level
691 backlight_set(get_backlight_level());
695 bool is_breathing(void)
697 return (TIMSK1 && _BV(OCIE1A));
700 void breathing_intensity_default(void)
702 //breath_intensity = (uint8_t)((uint16_t)100 * (uint16_t)get_backlight_level() / (uint16_t)BACKLIGHT_LEVELS);
703 breath_intensity = ((BACKLIGHT_LEVELS - get_backlight_level()) * ((BACKLIGHT_LEVELS + 1) / 2));
706 void breathing_intensity_set(uint8_t value)
708 breath_intensity = value;
711 void breathing_speed_default(void)
716 void breathing_speed_set(uint8_t value)
718 bool is_breathing_now = is_breathing();
719 uint8_t old_breath_speed = breath_speed;
721 if (is_breathing_now)
723 // Disable breathing interrupt
724 TIMSK1 &= ~_BV(OCIE1A);
727 breath_speed = value;
729 if (is_breathing_now)
731 // Adjust index to account for new speed
732 breathing_index = (( (uint8_t)( (breathing_index) >> old_breath_speed ) ) & 0x3F) << breath_speed;
734 // Enable breathing interrupt
735 TIMSK1 |= _BV(OCIE1A);
740 void breathing_speed_inc(uint8_t value)
742 if ((uint16_t)(breath_speed - value) > 10 )
744 breathing_speed_set(0);
748 breathing_speed_set(breath_speed - value);
752 void breathing_speed_dec(uint8_t value)
754 if ((uint16_t)(breath_speed + value) > 10 )
756 breathing_speed_set(10);
760 breathing_speed_set(breath_speed + value);
764 void breathing_defaults(void)
766 breathing_intensity_default();
767 breathing_speed_default();
768 breathing_halt = BREATHING_NO_HALT;
771 /* Breathing Sleep LED brighness(PWM On period) table
772 * (64[steps] * 4[duration]) / 64[PWM periods/s] = 4 second breath cycle
774 * http://www.wolframalpha.com/input/?i=%28sin%28+x%2F64*pi%29**8+*+255%2C+x%3D0+to+63
775 * (0..63).each {|x| p ((sin(x/64.0*PI)**8)*255).to_i }
777 static const uint8_t breathing_table[64] PROGMEM = {
778 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 4, 6, 10,
779 15, 23, 32, 44, 58, 74, 93, 113, 135, 157, 179, 199, 218, 233, 245, 252,
780 255, 252, 245, 233, 218, 199, 179, 157, 135, 113, 93, 74, 58, 44, 32, 23,
781 15, 10, 6, 4, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
784 ISR(TIMER1_COMPA_vect)
786 // OCR1x = (pgm_read_byte(&breathing_table[ ( (uint8_t)( (breathing_index++) >> breath_speed ) ) & 0x3F ] )) * breath_intensity;
789 uint8_t local_index = ( (uint8_t)( (breathing_index++) >> breath_speed ) ) & 0x3F;
791 if (((breathing_halt == BREATHING_HALT_ON) && (local_index == 0x20)) || ((breathing_halt == BREATHING_HALT_OFF) && (local_index == 0x3F)))
793 // Disable breathing interrupt
794 TIMSK1 &= ~_BV(OCIE1A);
797 OCR1x = (uint16_t)(((uint16_t)pgm_read_byte(&breathing_table[local_index]) * 257)) >> breath_intensity;
807 __attribute__ ((weak))
808 void backlight_init_ports(void)
813 __attribute__ ((weak))
814 void backlight_set(uint8_t level)
822 // Functions for spitting out values
825 void send_dword(uint32_t number) { // this might not actually work
826 uint16_t word = (number >> 16);
828 send_word(number & 0xFFFFUL);
831 void send_word(uint16_t number) {
832 uint8_t byte = number >> 8;
834 send_byte(number & 0xFF);
837 void send_byte(uint8_t number) {
838 uint8_t nibble = number >> 4;
840 send_nibble(number & 0xF);
843 void send_nibble(uint8_t number) {
847 unregister_code(KC_0);
850 register_code(KC_1 + (number - 1));
851 unregister_code(KC_1 + (number - 1));
854 register_code(KC_A + (number - 0xA));
855 unregister_code(KC_A + (number - 0xA));
860 void api_send_unicode(uint32_t unicode) {
863 dword_to_bytes(unicode, chunk);
864 MT_SEND_DATA(DT_UNICODE, chunk, 5);
868 __attribute__ ((weak))
869 void led_set_user(uint8_t usb_led) {
873 __attribute__ ((weak))
874 void led_set_kb(uint8_t usb_led) {
875 led_set_user(usb_led);
878 __attribute__ ((weak))
879 void led_init_ports(void)
884 __attribute__ ((weak))
885 void led_set(uint8_t usb_led)
890 // // Using PE6 Caps Lock LED
891 // if (usb_led & (1<<USB_LED_CAPS_LOCK))
908 //------------------------------------------------------------------------------
909 // Override these functions in your keymap file to play different tunes on
910 // different events such as startup and bootloader jump
912 __attribute__ ((weak))
913 void startup_user() {}
915 __attribute__ ((weak))
916 void shutdown_user() {}
918 //------------------------------------------------------------------------------